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 not let or have.

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