-
Notifications
You must be signed in to change notification settings - Fork 38
Conversation
guard /* i1 */ denom /* i2 */ !== /* i3 */ 0 /* i4 */ else { | ||
0 | ||
} | ||
// t5 |
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.
This needs fixing
Postponing this, as this is purely additive and we need to focus on tweaking some things that'd break code if we don't ship now, e.g. (Latter seems to be causing some nontrivial regression in the benchmarks) |
@tomgasson We are interested in this PR. Is there anyway to avoid introducing a keyword Edit: seems assert is already a keyword. how about this:
|
The assert is neat. However guard let Some(a) = myOptional else {
// "early return" logic
}
... Which is the cousin of: if let Some(a) = myOptional {
// "early return" logic
}
... I wonder if |
https://stackoverflow.com/questions/32256834/swift-guard-let-vs-if-let |
Not the same for us though; Swift handles if let Some(student) = payload.student
let Some(score) = student.score {
Js.log(score)
} else {
// ...
} |
For people who are interested in this PR, this answer explains the motivation very well |
How would that be better than switch + pattern matching? (The stated example would probably be nicer with that I think?). switch payload.student {
| Some({score: Some(score)}) => Js.log(score)
| _ => // ...
} |
Destructuring on a record wouldn't work with more elaborate examples. Perhaps I should have taken another example. switch payload.student {
| None => // ...
| Some(student) =>
switch process(student.score) {
| None => // ...
| Some(score) => Js.log(score)
}
} vs if let Some(student) = payload.student
let Some(score) = process(student.score) {
Js.log(score)
} else {
// ...
} There are drawbacks too of course. Mainly:
That's part of why Anyway, I've added the context as a reply to Bob of a few other things to maybe consider. Or not! |
@bobzhang Can you elaborate a bit on what you mean by the cost of the |
@IwanKaramazow
In general, I think we should hold a high bar when considering adding new keywords. Otherwise, whenever we plan to add a feature, we can always introduce a new keyword, it is not sustainable. |
Yeah I think if we ever accept this feature, |
I do not think |
I like the scrutiny here, that high bar is what makes the language great. I don't have any other suggestions, but not too keen on
|
Assert without else will abort as before. With else it will go the other branch. |
note if we can figure out a better syntax without introducing a new keyword, I would be happy to see it. The assert seems to be the best candidate here |
I didn't call it out clear enough but my implementation here doesn't line up with your assumption there. This implementation has Classical
Using
|
Ah, what I proposed is a generalized assert. I will write down the semantics later |
Here is my proposal of generalized assert.
assert predicate ;
follow_body The semantics is equivalent to if not predicate {
assert false // this type checks since `assert false` unifies with any type
} else {
follow_body
}
assert predicate else { console.error("BOOM"); exit(1)}
follow_body The semantics is equivalent to if not predicate {
console.error("BOOM");
exit (1) // type a
} else {
follow_body // type b
}
// type a should unify with type b
assert let Some (x) = x ;
follow_body rewrite to switch x {
Some (x) => follow_body
_ => assert false
}
assert let Some (x) = x else { other_expression}
follow_body rewrite to switch (x) {
Some (x) => follow_body
_ => other_expression
}
assert let Some (x) = x else {exp_x}
assert let Some (y) = y else {exp_y}
follow_body rewrite to
This illustrates how indentation hell is solved using |
The generalized assert looks quite nice and natural. A couple of code examples: Compared with the current code: edit: see chenglou's post below @cknitt what do you think of these examples? |
The proposal looks enticing. However I'm not sure @IwanKaramazow's examples work out. Here's what the examples would look like currently:
The sweet spot might be a long function body with a single assert or two at the top...? If that's worthwhile. |
I think the early returns instead of indentation hell are really great! 👍 My concern is just with the keyword
I think for newcomers, this may be confusing, and they may forget the else and end up inadvertently crashing the program. Experienced developers, on the other hand, when reading the keyword For me, when I see those asserts in the code, I think they will probably make me nervous every time and cause me to double check that I didn't forget the else... That's why I would prefer the Dumb question: Why do we need the So in short my preference would be to have just |
I keep somewhat getting tripped up by both examples (with I was wondering why it kept feeling like mental gymnastics, but that's because it's read as: "guard that something is true but otherwise return this" which translates to "if this is false the next line runs". Whereas every other if statement is that "if this is true this piece of code runs". Ruby has the
And pattern based....
This still uses the EDIT: I suppose some of this is covered by Eric Cerney's article linked in the OP but I thought I'd share anyway. |
I definitely agree with @cknitt. It also would be very convinient if |
It is |
@cknitt The Note I would like to add another use case besides solving the indentation hell issue. It makes it possible to write bare metal efficient code for cases like below: let hd = (hs) => {
let len = List.length (hs)
if (len > 0) {
assert let list{hd, ...} = hs
hd
} else {
..
}
} The snippet above is a contrived example, the idea is that there are some cases when you know the pattern match is for sure to succeed, you can use |
|
Status on this? |
There's more related discussion here: rescript-lang/rescript#5628 Basically, there are mixed opinions on how to introduce something like this. So it's been pretty much sitting there. |
The rescript-lang/syntax repo is obsolete and will be archived soon. If this issue is still relevant, please reopen in the compiler repo (https://github.com/rescript-lang/rescript-compiler) or comment here to ask for it to be moved. Thank you for your contributions. |
This introduces syntax sugar to allow early return. This comes in 2 forms:
Conditional....
And pattern based....
Which de-sugar into these respectively
and
This reduces rightward drift and nesting, and allows top-down control flow through preconditions
Precedence
reasonml/reason#1302
Swift