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
$true
and 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
if
form 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
when
andunless
, if implemented as syntactic sugar in the way you've described. If a constructor used anywhere in<expr>
is declaredpartial
and returnsNone
, then the entireif-let
doesn't match. So you could have a pair of rules which are identical except that one useswhen
and 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-let
should have an internalallow_partial
flag, set tofalse
forwhen
/unless
andtrue
for a realif-let
. Then, insema.rs
, intranslate_iflet
, pass theallow_partial
flag totranslate_expr
where it currently just passestrue
for theon_lhs
parameter. 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
when
andunless
forms. We could quibble about whetherwhen
should 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 ofif
and 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
,when
andunless
all 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 $true
toif
, and updating predicate definitions).I do agree that disallowing partial constructors in
if
/when
andunless
seems right!
Kmeakin commented on issue #6082:
Removing
if
would 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 23 2024 at 13:07 UTC