-
Notifications
You must be signed in to change notification settings - Fork 205
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
If-case expressions #3059
Comments
Edit: actually, if guards are expected to always diverge, then it's a different thing. |
You're right, this is a missing cell in the table. (The other missing one is switch collection elements.) It's tricky because Or we could try to build some weird pattern-based var x = foo case [a, b] ? something(a, b) : somethingElse(); That's actually not horrible, but it feels really weird to double down on |
The first thing I tried before filing this issue was using |
We could make I'm not personally a fan of the In any case, for now a (e1 case pattern when e2) ? e3 : e4 can be expressed as switch (e1) { pattern when e2 => e3, _ => e4 } It's somewhat longer. The |
As another anecdote, I did try parenthesizing the |
Technically, those aren't expressions either. They're elements. Because the things in the branches aren't always expressions: Part of the reason this works is that collection elements have a natural way to handle zero values being produced, which is what you get from an |
That's why I said "from a user's perspective" 😆. You and I both know the spec doesn't think about them as expressions, but when you're just writing code what really matters is "I can use Anyway, my vote here is to allow |
To me, a case expression would be most useful in obtaining a boolean for whether an object is a match to a certain pattern. Where a case expression could give us a one liner: final isMatch = foo case Bar(baz: Qux()); The only equivalents today seem unnecessarily verbose. final isMatch = switch (foo) {
Bar(baz: Qux()) => true,
_ => false,
} // bool checkMatch(Object foo) { <- for context
if (foo case Bar(baz: Qux()) {
return true;
} else {
return false;
}
// } I think another benefit of treating cases as a boolean expression would be that it is much more intuitive to use them with the tertiary |
I too would like But until then, I can work with With a grammar of <expression> ::=
<expressionWithoutCase>
| <caseExpression>
<expressionWithoutCase> ::=
<assignableExpression> <assignmentOperator> <expression>
| <conditionalExpression>
| <cascade>
| <throwExpression>
<expressionWithoutCascade> ::=
<expressionWithoutCascadeAndCase>
| <caseExpressionWithoutCascade>
<expressionWithoutCascadeAndCase> ::=
<assignableExpression> <assignmentOperator> <expressionWithoutCascade>
| <conditionalExpression>
| <throwExpressionWithoutCascade>
<caseExpression> ::=
<expressionWithoutCase> `case' <pattern> (`when` <expressionWithoutCase>)?
<caseExpressionWithoutCascade> ::=
<expressionWithoutCascadeAndCase> `case' <pattern> (`when` <expressionWithoutCascadeAndCase>)? By placing it so high in the syntax hiearachy, it'll need parentheses almost everywhere. And no nesting unparenthesized The condition of a (But we can treat Semantics is that the if (!(foo case Bar(:var bar)) return;
bar.barbarbar(); will work, and any other logical combination. I think users will understand that, it's exactly the same scope where promotion works. |
I have instinctively tried to transform this: bool _validateUri(Uri uri) {
return uri.path == '/path' &&
uri.queryParameters['param1'] == 'param1' &&
uri.queryParameters['param2'] == 'param2' &&
uri.queryParameters['param3'] != null &&
uri.queryParameters['param4'] != null;
} into this: bool _validateUri(Uri uri) {
return uri.path == '/path' && uri.queryParameters case {
'param1': 'param1',
'param2': 'param2',
'param3': String _,
'param4': String _,
};
} and was surprised that this is not a valid syntax. Are there any plans for this feature? |
No concretely worked-on plans for expression-case-if. I personally (still) think a bool _validateUri(Uri uri) {
return uri.path == '/path' && (uri.queryParameters case {
'param1': 'param1',
'param2': 'param2',
'param3': String _,
'param4': String _,
});
} Parentheses would likely be required when used as sub-expression of another expression. |
(Sorry if this is already filed, I did do a search but GitHub's search is pretty rough for something with this broad a name.)
One hole I've run into when working on converting existing code to Dart 3 style is the absence of an expression-level "if-case". To put it another way, there's a gap in the following matrix:
if (foo case [a, b]) {} else {}
switch (foo) {case [a, b]: /* ... */}
switch (foo) {[a, b] => /* ... */}
I'd expect to either be able to use
case
with a ternary expression, or to be able to use the existing if-case syntax at the expression level (possibly without brackets to match the collection literal syntax), but neither of these works. I could use aswitch
expression here, but it involves more and more awkward nesting thanif
or ternary expression would. I think the shortest way to express this right now is actually:...but that's too silly to even consider.
(Addendum: pattern matching is a wonderful feature and I'm very excited to use it in Dart.)
The text was updated successfully, but these errors were encountered: