Zulip Chat Archive
Stream: new members
Topic: Way to use `set` without having to copy-paste expression?
Jakub Nowak (Jan 06 2026 at 21:26):
Is it possible to do the same, but without having to mention some_long_and_complicated_expr? E.g., by selecting it with conv => lhs.
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = 0 := by
set p := some_long_and_complicated_expr
Aaron Liu (Jan 06 2026 at 21:28):
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = 0 := by
refine let p := _; (?_ : p = _)
Jakub Nowak (Jan 06 2026 at 21:32):
Is there a way to do let instead of set?
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = 0 := by
let p := some_long_and_complicated_expr
Jakub Nowak (Jan 06 2026 at 21:33):
I guess I can just unfold p.
Aaron Liu (Jan 06 2026 at 21:33):
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = 0 := by
refine let p := _; (?_ : zeta% p = _)
Jakub Nowak (Jan 06 2026 at 21:36):
Is that idiomatic? I could find any use of that pattern in mathlib.
Aaron Liu (Jan 06 2026 at 21:37):
no idea
Aaron Liu (Jan 06 2026 at 21:37):
but it works
Aaron Liu (Jan 06 2026 at 21:37):
I don't really know a better way
Robin Arnez (Jan 06 2026 at 21:38):
I would've first thought about
show ?a = 0
let p := ?a
Aaron Liu (Jan 06 2026 at 21:39):
then you end up with a named metavariable
Aaron Liu (Jan 06 2026 at 21:39):
so it doesn't work for example if there's already something called ?a
Aaron Liu (Jan 06 2026 at 21:40):
and you also can't ever use the name ?a again in that proof
Aaron Liu (Jan 06 2026 at 21:40):
or maybe in the by block? I don't really know how this works
Ruben Van de Velde (Jan 06 2026 at 21:40):
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = 0 := by
set p := _
change p = 0
sorry
seems to work
Ruben Van de Velde (Jan 06 2026 at 21:43):
Does it work robustly? I haven't a clue
Aaron Liu (Jan 06 2026 at 21:46):
I wonder if we can get like an expression language? to manipulate expressions
Jakub Nowak (Jan 06 2026 at 21:56):
@Aaron Liu Isn't that conv? Maybe we could have a conv tactic that does set/let on current conv goal? Something like
conv
lhs
set p
Aaron Liu (Jan 06 2026 at 21:57):
not really
Aaron Liu (Jan 06 2026 at 21:57):
conv has to prove the new expression is equal to the original
Ruben Van de Velde (Jan 06 2026 at 21:57):
I think a tactic like foo ?p = ?x + ?y would be cool
Jakub Nowak (Jan 06 2026 at 22:10):
Unfortunately all mentioned ways require repeating names of functions and don't work well with dot notation.
import Mathlib
opaque some_long_and_complicated_expr : Nat
opaque Nat.some_long_function_name : Nat → Prop
example : some_long_and_complicated_expr.some_long_function_name := by
set p := _
change Nat.some_long_function_name p
Aaron Liu (Jan 06 2026 at 22:12):
import Mathlib
opaque some_long_and_complicated_expr : Nat
opaque Nat.some_long_function_name : Nat → Prop
example : some_long_and_complicated_expr.some_long_function_name := by
set p := _
conv =>
enter [1]
change p
guard_target =ₛ p.some_long_function_name
sorry
Matt Diamond (Jan 06 2026 at 22:44):
you can also use change with metavariables before the set statement (e.g. change ?x = ?y; set x := ?x; set y := ?y) but I'm guessing that runs into the same drawbacks as the other approaches (with the additional drawback that Lean complains about the change tactic not accomplishing anything)
Bbbbbbbbba (Jan 16 2026 at 09:18):
Is there a way discussed here that works for reducing duplication in the declaration of the statement to prove? (In plain words, what if some_long_and_complicated_expr appears within the statement many times?)
Jakub Nowak (Jan 16 2026 at 10:28):
Exactly the same should work, because set replaces all occurrences of an expression. It doesn't work for you?
Nvm, it indeed doesn't work with set p := _; conv approach.
Jakub Nowak (Jan 16 2026 at 10:33):
It works with change if you repeat p:
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = some_long_and_complicated_expr + 1 := by
set p := some_long_and_complicated_expr
guard_target =ₛ p = p + 1
example : some_long_and_complicated_expr = some_long_and_complicated_expr + 1 := by
set p := _
change p = p + 1
guard_target =ₛ p = p + 1
example : some_long_and_complicated_expr = some_long_and_complicated_expr + 1 := by
set p := _
conv =>
lhs
change p
guard_target =ₛ p = some_long_and_complicated_expr + 1
Anyone understands why the last one doesn't work, and whether we could fix this? Tbh, I don't even understand why it even works in the first place, specifically why it only works with set, but not let or have.
Aaron Liu (Jan 16 2026 at 11:09):
It's because set does replacement when you run the tactic and not at any time after
Aaron Liu (Jan 16 2026 at 11:10):
Jakub Nowak said:
Tbh, I don't even understand why it even works in the first place, specifically why it only works with
set, but notletorhave.
Maybe a metavariables thing?
Jakub Nowak (Jan 16 2026 at 11:12):
This works:
import Mathlib
opaque some_long_and_complicated_expr : Nat
example : some_long_and_complicated_expr = some_long_and_complicated_expr + 1 := by
set p' := _
conv =>
lhs
change p'
unfold p'
set p := zeta% p'
clear p'
Jakub Nowak (Jan 16 2026 at 11:13):
Is there a tactic that combines unfold, set, and clear?
Last updated: Feb 28 2026 at 14:05 UTC