Kmeakin opened issue #6082:
Feature
Add
(when <expr>)and(unless <expr>)syntax as shorthand for(if-let $true <expr>)and(if-let $false <expr>)respectivelyBenefit
Less to type when adding boolean conditions to rules
Implementation
Should be simple to implement as a syntax sugar rewrite in the ISLE compiler
Alternatives
Leave ISLE unchanged
Kmeakin edited issue #6082:
Feature
Add
(when <expr>)and(unless <expr>)syntax as shorthand for(if-let $true <expr>)and(if-let $false <expr>)respectivelyBenefit
Less to type when adding boolean conditions to rules
Implementation
Should be simple to implement as a syntax sugar rewrite in the ISLE compiler. I would be happy to implement it myself.
Alternatives
Leave ISLE unchanged
cfallin commented on issue #6082:
We've definitely talked about this sort of thing before. I think the root issue is actually that we have ctors that communicate a predicate by their truthy return value as well as other ctors that communicate a predicate by matching or not matching. We should decide one way or another, and then make the existing
(if ...)shorthand (which uses the RHS as a match/no-match predicate rather than a truthy predicate) fit that decision.@jameysharp, IIRC there were good reasons why we started returning values more frequently rather than using the matching status itself -- was it to allow for better islec codegen?
If that's the case, one way forward would be to (i) audit all predicates and convert them from "matchy" to "truthy"; then (ii) make
(if x)sugar for(if-let $true x).This strikes me as more type-safe than the other way around: if we keep
(if x)as(if-let _ x)any truthy predicate gets matched when it returns$false(the silent bug we had before), whereas with(if-let $true x)we are likely to get a type error if a matchy predicate (that e.g. returns Unit or passes through a value it took in) is used.It is a little odd to bake in
$trueand the bool type to the language (currently these are a$-passthrough symbol and a type defined in the prelude, respectively) but, eh... it's certainly more ergonomic.
jameysharp commented on issue #6082:
I like this idea. We currently have an
(if <expr>)form which is also syntactic sugar forif-let, so you can model these new forms off of that.Separately, we should probably delete the
ifform since it doesn't do what you'd expect. It's used in quite a few places though and we'd need to think about how to fix the existing uses.Here's one thing that's surprising about
whenandunless, if implemented as syntactic sugar in the way you've described. If a constructor used anywhere in<expr>is declaredpartialand returnsNone, then the entireif-letdoesn't match. So you could have a pair of rules which are identical except that one useswhenand the other usesunless, and find that neither one matches. And you can't tell by looking at a rule if that's going to happen; you'd have to check every single term it references.In the interests of reducing surprises, I think the desugared
if-letshould have an internalallow_partialflag, set tofalseforwhen/unlessandtruefor a realif-let. Then, insema.rs, intranslate_iflet, pass theallow_partialflag totranslate_exprwhere it currently just passestruefor theon_lhsparameter. That'll trigger the existing checks which prohibit partial terms in other circumstances.@cfallin, using boolean results allows us to write rules that the overlap checker can tell don't overlap without needing to set different priorities on the rules. That in turn sometimes helps generate better code, but the overlap checking was the main reason. As I recall, it was @elliottt who figured out the value of that pattern, when he started to fix overlapping rules.
Because of the value for overlap checking, I think @Kmeakin is right that it's a good idea to have both the
whenandunlessforms. We could quibble about whetherwhenshould instead be namedif. The very distant memories I have of writing Perl make me feel like that's the "right" counterpart tounless, but in the interests of not having to change everything at once, I think we should preserve the current behavior ofifand migrate away from it over time.
cfallin commented on issue #6082:
I think we should preserve the current behavior of if and migrate away from it over time.
I'm usually very much in favor of this sort of approach (see: ISLE!), but in this case I worry about the cognitive overhead and confusion to new users if
if,whenandunlessall exist at the same time, with confusingly subtle semantic differences. I suspect that flipping the semantics ofif(or renaming towhen, I don't care much either) and doing one bulk-changeover in the backends would not be too bad -- a fairly mechanical change (find-replaceif-let $truetoif, and updating predicate definitions).I do agree that disallowing partial constructors in
if/whenandunlessseems right!
Kmeakin commented on issue #6082:
Removing
ifwould also allow us to have an(if <cond> <then> <else>)expression
jameysharp added the isle label to Issue #6082.
github-actions[bot] commented on issue #6082:
Subscribe to Label Action
cc @cfallin, @fitzgen
<details>
This issue or pull request has been labeled: "isle"Thus the following users have been cc'd because of the following labels:
- cfallin: isle
- fitzgen: isle
To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.
Learn more.
</details>
Last updated: Dec 13 2025 at 19:03 UTC