Add "if <term> is <pattern> then _ else _" syntax#21609
Add "if <term> is <pattern> then _ else _" syntax#21609proux01 wants to merge 2 commits intorocq-prover:masterfrom
Conversation
Not sure we want this. Not sure about |
I don't like that, it reverses the term and the pattern, making it look different than the match-with usual syntax.
Yes, for instance for the common idiom |
|
|
|
|
|
I would say that the |
Would avoid making
Well, at this point we can just write the match.
If you write things like Don't forget that we have more than a decade of experience with the syntax in the entire mathcomp ecosystem and that it seems to work pretty well (at least in that context). |
|
My understanding is that the syntax of mathcomp is the main barrier for adoption. Which is not to mean that it's an argument to reject the notation, but just "trust me" seems a bit weak as argument for it. But I'm not part of the Rocq team so I will not fight against it of course. Just to clarify I'm not trying to be mean, I just wanted to express my concerns and it's very likely misplaced. |
|
I find the Rust |
The argument is not "trust me", rather: it has been used extensively, by many people for a long time, and proved effective (at least in that context, maybe more math oriented than PL community). You can browse all the codebase by yourself if you want to check.
No worries, any opinion is welcome, as long as it remain based on concrete arguments and facts.
I can indeed see that syntax fitting better in the C-like syntax of Rust (where "if" may be the primary control structure, no "then" keyword, no "in" keyword for "let",...) but it doesn't fit well in the ML like syntax of Rocq (with "match" being the main control structure, with "with" and "then" keywords, "let" always followed by "in",...). As already pointed above, such syntaxes with "let" reverse the order of the term and the pattern compared to the usual "match term with (| pattern => term)* end" syntax. |
I don't think that's really a problem, we already have |
|
That's my point, the pattern in let is only doing some destructuring, no control flow, since a let is a match with a single branch. In contrary, an if is essentially a match with multiple branches. The case where the else branch is the main one (not uncommon, think about nat or list for instance) also remains unclear in that kind of proposals. Anyway, I tried to sum up the discussion in the top message, feel free to point any argument I would have forgotten. |
|
Another alternative could be to change unless t is p then _ else _The main advantage I see is that the pattern matching clause is still framed positively, so it restores, in my mind, the idea that some new variables are bound. In any case, doesn't this syntax encourage bad matching like the following? if n is 3 then _ else _To me it now feels more natural to write, but you should actually not do it. You can make things worse by using a string rather than |
|
I agree with @proux01 that the large-else-branch scenario is important and could benefit from nice shorthand syntax. (Thank you for stressing it, I had been thinking about the Here are some more options that come to mind that I would hope to be broadly recognizable:
and
To be confirmed whether they're compatible with the grammar, though. |
|
Indeed, a construct that allowed me to write short error handling branches before a main branch that does not get formatted at a higher level of indentation, like eg the following, seems useful: let 'x::xs := myList else None in
some lengthy code referring to x and xs;
formatted without an additional level of indentation;
finally returning
Some resultOr, if I understood correctly, the same using if myList isn't x::xs then None else
some lengthy code referring to x and xs;
formatted without an additional level of indentation;
finally returning
Some result |
|
@samuelgruetter added to the if-let offer in the top message |
|
To be discussed in a future Call: https://github.com/rocq-prover/rocq/wiki/Rocq-Call-2026-03-17 |
|
BTW we already have rocq/theories/Corelib/Init/Notations.v Line 113 in c4fa328 |
I know, note that there is a small difference in the handling of shallow scope opening (which goes through each branches of the native match but not through the notation) |
|
Lean seems to support |
New syntactic sugar
if g is c then t else eandif g isn't c then t else eformatch g with c => t | _ => e endandmatch g with c => e | _ => t endrespectively. This adds the new reserved keywordsisandisn'tSplit out of #21478
In the long run (not this PR) we should maybe deprecate the specific if ... then ... else for inductives with two constructors (that is error prone, since it depends from the order of the constructors) with a quickfix toward the new if g is first_constructor then ... else variant and restrict if ... then ... else to booleans (or anything coercible to bool)
Documented any new / changed user messages.make doc_gram_rsts.Overlays (to be merged before the current PR)
Alternative
In the discussion below, some alternative syntax proposition came out. Respective advantages:
if <term> is <pattern> then <term> else <term>andif <term> isn't <pattern> then <term> else <term>if let <pattern> := <term> then <term> else <term>andlet <pattern> := <term> else <term> in <term>iskeyword