Zulip Chat Archive

Stream: new members

Topic: Is it possible to have genuine abbreviations?


Ching-Tsun Chou (Aug 27 2025 at 21:48):

Consider the following definition:

variable (x y z : )
abbrev foo := x + y + z

Subsequently the term foo denotes a function foo : ℕ → ℕ → ℕ → ℕ, not the sum x + y + z. To refer to that sum, I need to write foo x y z. After all, abbrevis just a variant of def. But is it possible to have a genuine abbreviation or "macro" so that I can write foo for the expression x + y + z?

Needless to say, in the actual use case I have in mind, the identifiers and expressions involved are more complicated than those in the above example and I hope a genuine abbreviation mechanism can improve the readability of my code.

Niels Voss (Aug 27 2025 at 21:52):

In Lean 3, there used to be a parameter command which did something similar, but it was removed in Lean 4 for reasons I don't quite understand. You can probably do something like local notation "foo" => x + y + z, and I know this is possible to implement using macros.

Ching-Tsun Chou (Aug 27 2025 at 21:54):

Is this documented somewhere or there are examples I can look at?

Niels Voss (Aug 27 2025 at 21:58):

I'm not sure, sorry. One thing to watch out for is this bug #general > Local notation leads to hidden sorry. It's possible it has been fixed, but I haven't checked recently.

Niels Voss (Aug 27 2025 at 22:01):

I think the bug is still present

Jakub Nowak (Aug 27 2025 at 22:06):

Macro also works macro "foo" : term => (x + y + z)`.

Jakub Nowak (Aug 27 2025 at 22:08):

import Mathlib

variable (x y z : )

macro "foo" : term  => `(x + y + z)

abbrev bar := x + y + z

theorem foobar : foo = bar x y z := by rfl

-- doesn't work (as expected)
-- theorem foobar2 x y z : foo = bar x y z := by rfl

Jovan Gerbscheid (Aug 28 2025 at 17:35):

Yes, you can do it as follows using local notation:

local notation "foo" x:max y:max z:max => x + y + z
variable (x y z : Nat)

example : foo x y z = foo y z x := by
  omega

The local just means that the notation isn't defined globally. Writing x:max instead of x tells Lean about the precedence it needs to use to parse x. Without this, it would think that foo x y z is foo (x y z), i.e. x applied to y and z.

Ching-Tsun Chou (Aug 28 2025 at 17:44):

I'm not sure that's what I wanted. What I wanted is to write foo for the expression x + y + z without having to mention any of x, y, and z.

Kyle Miller (Aug 28 2025 at 17:47):

I suggest searching for examples of local notation in mathlib. There are plenty that capture variables defined in variables.

Terence Tao (Aug 28 2025 at 18:45):

One compromise that works for me is to place all ambient variables inside a custom class that one then exports back to the environment, and also introduces as a variable instance. Abbreviations then depend on that class instance, but that is handled invisibly and so it becomes visually indistinguishable from a "genuine" abbreviation. Example:

import Mathlib

class Data where
  x:
  y:
  z:

export Data (x y z)

variable [Data]

abbrev foo := x + y + z

example : foo = x + y + z := rfl

Last updated: Dec 20 2025 at 21:32 UTC