Zulip Chat Archive
Stream: lean4
Topic: pretty-printing puzzle
Damiano Testa (Jul 08 2025 at 19:36):
Here is something that surprised me.
How do you think that the pretty-printer prints these?
#check s!""
#check s!"{1}"
Answer
Mario Carneiro (Jul 08 2025 at 20:30):
I guess this is because s! takes a term <|> interpolatedStr(term) and so they may be handled differently
Thomas Zhu (Jul 08 2025 at 22:59):
macro:max "mys!" interpStr:interpolatedStr(term) : term =>
do interpStr.expandInterpolatedStr (← `(String)) (← `(toString))
run_cmd
let s1 ← `(term| mys!"")
let s2 ← `(term| mys!"{1}")
Lean.logInfo s1
Lean.logInfo s2
Output:
mys!""
mys! "{1}"
Thomas Zhu (Jul 08 2025 at 23:33):
Input:
syntax "a" interpolatedStr(term) : term
syntax "!" interpolatedStr(term) : term
run_meta
let s1 ← `(term| a"{1}")
let s2 ← `(term| !"{1}")
Lean.logInfo s1
Lean.logInfo s2
Output:
a "{1}"
!"{1}"
Aaron Liu (Jul 08 2025 at 23:34):
I guess s! is a valid identifier
Thomas Zhu (Jul 08 2025 at 23:34):
Is it something to do with docs#Lean.PrettyPrinter.Formatter.State.leadWordIdent ?
Thomas Zhu (Jul 08 2025 at 23:56):
I think it's this line https://github.com/leanprover/lean4/blob/7c3ca70e29a0806bd4bfc62eae7084bbaf1a303d/src/Lean/PrettyPrinter/Formatter.lean#L386
Thomas Zhu (Jul 08 2025 at 23:57):
syntax "t!" term : term
run_meta
logInfo (← `(term| t! ""))
logInfo (← `(term| t! fun _ => _))
logInfo (← `(term| t! λ _ => _))
logInfo (← `(term| t! 1))
logInfo (← `(term| t! -1))
logInfo (← `(term| t! _))
Thomas Zhu (Jul 08 2025 at 23:58):
t!fun, t!1, and t!_ are valid identifiers, so spaces are inserted
Damiano Testa (Jul 09 2025 at 06:37):
Thank you all for your comments! I do not know if I understand better or worse what is going on now. :upside_down:
Damiano Testa (Jul 09 2025 at 07:16):
Here is another:
#check let a := 0;0
#check let (a) := 0;0
Pretty printed
Thomas Zhu (Jul 09 2025 at 07:25):
I think this is the same idea: leta would be seen as a single identifier, so a space is inserted
Damiano Testa (Jul 09 2025 at 07:25):
I agree, I think that the other is the weird one, though.
Thomas Zhu (Jul 09 2025 at 07:27):
I agree, I think what happens is that somehow the tokenFn consumes beyond s! in s!"{, or maybe it's some other corner case that I didn't identify
Thomas Zhu (Jul 09 2025 at 07:27):
(I don't have time to look into the details)
Thomas Zhu (Jul 09 2025 at 07:28):
maybe we can use ppSpace in let and noWs in s! to eliminate the differences in behavior
Damiano Testa (Jul 09 2025 at 07:41):
I agree that adding a ppSpace for let is probably a good solution. I am not so sure about noWs in the other case, though.
Thomas Zhu (Jul 09 2025 at 07:42):
I am not familiar with parsers in Lean, perhaps there is a much better solution
Mario Carneiro (Jul 09 2025 at 15:19):
noWs is not just a pretty printer thing, it makes it a parse error to add a space which we probably don't want
Aaron Liu (Jul 09 2025 at 15:38):
is there a ppNoWs?
Mario Carneiro (Jul 09 2025 at 15:44):
that's just the default
Mario Carneiro (Jul 09 2025 at 15:44):
spaces between tokens are never inserted unless they would be required by the lexer
Damiano Testa (Jul 09 2025 at 15:46):
Right now, I am developing a version of the commandStart that seems to be correctly identifying whitespace issues on the vast majority of mathlib.
Damiano Testa (Jul 09 2025 at 15:47):
The main nodes that I have to silence are tactics such as apply and replace that, when followed by ( get pretty-printed without a space.
Mario Carneiro (Jul 09 2025 at 15:47):
those are all pretty printer bugs
Mario Carneiro (Jul 09 2025 at 15:47):
people don't use ppSpace as much as they should
Damiano Testa (Jul 09 2025 at 15:48):
If this could be fixed, then I think that most of the rest of the issues would be actually undetermined, so there could be a linter for whitespace on virtually everything in mathlib.
Damiano Testa (Jul 09 2025 at 15:48):
Mario Carneiro said:
people don't use
ppSpaceas much as they should
I agree and it looks like that is the major obstacle for trusting the pretty-printer from being a formatter.
Mario Carneiro (Jul 09 2025 at 15:49):
well no, I think the high level layout algorithm is not optimal for a formatter
Damiano Testa (Jul 09 2025 at 15:50):
Ah, I keep forgetting: the linter trusts line-breaks in the source, but spaces in the pretty-printer.
Last updated: Dec 20 2025 at 21:32 UTC