-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: let ... else
binding
#3817
Conversation
by just not diagnosing anything
and remove some trailing spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some interim comments on doc. Now looking at code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments. I'm still worried by some of those pattern matches on None.
@@ -771,35 +771,35 @@ and define_id env id v = | |||
Lib.Promise.fulfill (find id.it env.vals) v | |||
|
|||
and define_pat env pat v = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning a bool is nicer and more efficient I expect. Nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments. Generally looks good but I'm still worried by some of those pattern matches on None. The problem is that alot of our actor/module/object sugar desugars to let expressions (to support recursion) but the code to spot these may now fail or behave strangely differently when that desugaring suddenly contains a fail clause (because the author didn't use the sugar but programmed directly in the target language. I guess the problem wouldn't exist if people could not both write, e.g.
module X = {}
and
let X = module {}
but now also
let X = module {} else {...}
(and similarly for objects and actors).
The first two are treated the same by the compiler, but the last winds up being treated differently in some cases the programmer might not be expecting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job!
Original discussions in #3588.
New
let
binding that allows a failure block in case of a pattern-match failure. The main motivation for this feature is to avoid deeply nested switch statements that lead to less readable code.See forum discussion here.
Simple example:
The failure block must always have type
None
to ensure that execution does not continue beyond the failed binding. Failure blocks may thus trap, return out of the function, or break / continue if in the context of a loop.Failure blocks may also perform asynchronous effects, if the binding itself is in an asynchronous context.
More complex example:
Without this binding, you might have to either do the following
or
however this second version does not execute examples sequentially (i.e. even if
foo()
fails,bar()
andbaz()
will execute).With
let-else
bindings:Inspired by the same feature in rust
Items left to do:
else
as a block instead of a valuereturn
at the end ofelse
block return out of the functionrun
) and negative (fail
) testsreturn
,continue
,break
in failure part (also with 0, 1 and more return values)return
in monadic context (async
)await
in failure partM0500
is provisional) — not neededcompUnit.ml
)?None
pattern matchesOther PR:
type continuation = V.(value cont);
let-else
binding #3832Potential further optimisations:
let (b_1, b_2, ..., b_n) = switch { case <pat> (b_1, b_2, ..., b_n); ... };