-
Notifications
You must be signed in to change notification settings - Fork 213
if expressions #3374
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
Comments
Does this solves your problem? var x = switch ((a, b)) {
(> 0, _) => 1,
(_, < 10) => 2,
_ => 3,
}; |
It looks very non-intuitive. |
At least, there are if-expressions in Rust, Python, Kotlin and Swift, along with switch/match expressions: |
@subzero911, it looks like you are asking for a way to write statements in an var x = (){ if (a > 0) return 1; else return 2; }(); This would allow you to write arbitrary statements and deliver the result using
because there's no branching that you can't express using the In any case, you might very well want to preserve the context type, because this can affect the meaning of a statement like X iife<X>(X Function() f) => f();
double x = iife((){ if (a > 0) return 1; else return 2; }); This causes |
You can do everything with a conditional expression, The original example can be written as: var x = (a > 0) ? 1 : (b < 10) ? 2 : 3; Shorter. More like random line noise. But just as powerful. Switches can do more advanced branching. That said, I'd be happy to allow an |
var x = (a > 0) ? 1 : (b < 10) ? 2 : 3; This is a so-called "ternary hell", rather an example of "how you shouldn't do". |
@subzero911 Do you think |
How about this? var x = switch (null) {
_ when a > 0 => 1,
_ when b < 10 => 2,
_ => 3,
}; |
Agreed,
Yeah, we have
|
I personally don't like bringing every nice feature from other popular languages. Reason why IIFE looks good to me - I use it all the time with switch expression, however I always end up with extracting them to separate functions - for readability and documentation purposes. |
However, if Dart didn't choose to proceed with Pattern Matching and, instead, stuck to flow analysis, having if expression (instead of switch expressions) would be justifiable. |
May just be personal preference, but ternary expressions have been driving me absolutely mad. I desperately want an if...else expression so that I can completely avoid ternaries. Here are my arguments in favor of an if...else expression:
return
if (predA) 'A'
else if (predB) 'B'
else if (predC) 'C'
else null;
My spicy-hot take is that ternaries are a dated syntax that doesn't make a lot of sense in a modern language. Here are my thoughts on all the previous points made so far:
|
There is a ternary expression Not sure about the syntax, but instead of something like this:
the thought is to avoid the "null" part and write something like:
In a Flutter context it is commonly used for gesture callback, e.g. |
The example looks like it can just be x = condition ? y : null; or if assigning if (condition) x = y; Saving the It's also possible to implement this as an extension method. extension GuardOrNull on bool {
T? call<T>(T value) => this ? value : null;
} Which you can use as: x = (condition)(x); Biggest issue is that it doesn't promote. I think a new syntax is more important for conditionally passing arguments, like foo(1, x: if (o != null) o.length) so that book argument is passed if the condition is false. |
In your last assessment you don't take into account readability when And your example with an if statement can't be used when you need to return a value. Eg. Flutter reference in my comment:
Instead of extension on a boolean we could use a static method to be used like:
Though with an inline function declaration that will require an additional lambda, comparing with ternary or potential unary conditional expression. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Actually, there is an advantage of Rust's if expression compared to the ternary operator. let foo = if bar < 10 {
let x = 6;
let y = 7;
x + y
} else {
bar
} The nice part here is that we can use additional variables inside the if scope, while still avoiding a mutable variable. int foo = bar;
if (bar < 10) {
final x = 6;
final y = 7;
foo = x + y;
} There is no way to have foo being final without making the ternary operator ugly or introducing variables in the most outer scope. I miss this feature from Rust and I often find myself in these situations. But this is probably one of those problems that one can only have if they have experienced the other language. |
@domhel You can make final int foo;
if (bar < 10) {
final x = 6;
final y = 7;
foo = x + y;
} else {
foo = bar;
} It's slightly more verbose, but not impossible (and definitely more readable than using ternary). |
Readability is a subjective thing. But statements can't be used everywhere. E.g can't use them when building collections. |
Sure, I didn't say I'm against if expressions, I just informed him that for his specific case, it was not needed. |
We have "collection if" and "collection for" in Dart. |
I think it's unlikely that we'd add However, I do think we should allow a var x = switch {
when a > 0 => 1,
when b < 10 => 2,
=> 3,
}; That looks pretty nice to me. |
I ran into a new pain with ternaries: they don't (as far as I can tell) support pattern matching: // Syntax error.
final foo = (maybeFoo case final nonNullFoo?) ? processFoo(nonNullFoo) : Foo.defaultInstance; Could we at the very least get single-line if...else expressions? These would be more or less analogous to
This would allow us to replace every use of ternary syntax with an |
Correct, conditional expressions do not support case conditions. Switch expressions do, so you can write: final foo = switch (foo) { final nonNullFoo? => processFoo(nonNullFoo), _ => Foo.defaultInstance}; The formatter won't allow you to keep it on one line, though. The conditional expression might just be short enough to be allowed. Maybe. (Also, pet-peeve: The |
Here's an example from flutter dart:ui where I would have liked this: https://github.com/flutter/flutter/blob/c45b835577b01777e70681c7b751af82784ff3a4/engine/src/flutter/lib/ui/math.dart#L13 double clampDouble(double x, double min, double max) {
assert(min <= max && !max.isNaN && !min.isNaN);
if (x < min) {
return min;
}
if (x > max) {
return max;
}
if (x.isNaN) {
return max;
}
return x;
}
I only used this once and wanted to write it myself so I could remove the a =
x > max ? max:
x < min ? min:
x;
if the formatter supported that. I do also like this though: a = switch {
when x > max -> max,
when x < min -> min,
_ -> x
}
(non-constant expressions would need switch-when and plain switch would still be constant only, right?) However, I think Kotlin a = when {
x > max -> max,
x < min -> min,
_ -> x
}
I also think a = if {
x > max -> max,
x < min -> min,
else -> x,
}
looks good, which is similar to #3457 (comment) except as an expression. |
That's essentially #3457. I agree it would be nice.
That's correct. |
You already introduced switch expressions. Are you planning to add if expressions?
Syntax examples:
Currently we have only
x ? y : z
operator, but it's not enough if we want more advanced branching.The text was updated successfully, but these errors were encountered: