Zulip Chat Archive

Stream: lean4

Topic: Optional nodes in `elab`


πš πš˜πš“πšŒπš’πšŽπšŒπš‘ πš—πšŠπš πš›πš˜πšŒπš”πš’ (Feb 02 2026 at 03:52):

Is it a bug that the optional syntax node in TEST2 is resolved to none?

import Lean
open Lean

elab "TEST1" t:(term)? : term => do
  logInfo m!"t = {t}"
  return .sort .zero

elab "TEST2" t:("abc" term)? : term => do
  logInfo m!"t = {t}"
  return .sort .zero

elab "TEST3" t:optional("abc" term) : term => do
  logInfo m!"t = {t}"
  return .sort .zero

#check TEST1 10 -- t = some (10)

#check TEST2 abc 10 -- t = none

#check TEST3 abc 10 -- t = failed to pretty print term (use 'set_option pp.rawOnError true' for raw representation)

Robin Arnez (Feb 02 2026 at 09:26):

The reason why TEST2 produces none is that it uses docs#Lean.Syntax.getOptional? which returns none if there is more than one node inside (I guess otherwise it'd be ambiguous which node to take). And apparently ? is more special than optional since TEST3 just takes the raw syntax (["abc" (num "10")]) which the pretty-printer has no clue how to print.

πš πš˜πš“πšŒπš’πšŽπšŒπš‘ πš—πšŠπš πš›πš˜πšŒπš”πš’ (Feb 02 2026 at 17:16):

I'd say there is at the very least an inconsistency with the docstring on ?. It goes "(p)?Β is shorthand forΒ optional(p).", but that's not the case here. It might simply be a missing case in mkSyntaxAndPat.


Last updated: Feb 28 2026 at 14:05 UTC