-
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
unify the syntax of if-statements, collection ifs and the ternary operator #729
Comments
@tatumizer thanks for the link, that issue looks very similar. I don't advocate an operator that magically makes nulls disappear, though. That seems like it could lead to highly unintuitive code. What is the overall state of this? It seems important to figure out before nnbd is finalized. |
This issue consists of three orthogonal issues and one meta issue. |
What about if statements whose body is a block or some other statement? Are you proposing to make blocks become expressions too? If so, what does this do: var x = if (true) {} else {}; Is |
Flutter using a lot of named parameters, with many optional ones, I do agree on the idea of having a ìf`expression like with collections. It's a pain to have to write: SomeWidget(
parameter: condition ? value : null,
) It'd be a lot more readable if we could just write: SomeWidget(
parameter: if (condition) value,
) |
This is valid dart code:
It seems to be possible to distinguish between blocks for scoping and map literals. Could this also be used here? And if the branches contain more than the literal to be returned, I would propose the
I would assume that this could integrate nicely with the new infrastructure of NNBD
@munificent so I think that yes, I would propose to make blocks expressions, too. And I hope that the parser can disambiguate between blocks and map/set literals. |
Can't we statically differentiate Such as expression ifs can't have blocks (like with collection ifs), but statement ifs can. As such we have: Map? result = if (bool) {}
var result = if (bool) { print('42'); } // compile error vs: if (bool) {
print('42');
} From my understanding, this shouldn't cause any issue as expressions vs statements ifs don't overlap. We can't write: |
Yes. The way the language does that is by forbidding a map/set literal to appear at the beginning of an expression statement. In other words, in a context where the language knows you are writing a statement, it knows
Yes, it could. But I worry that the result is a very subtle rule that users would run into frequently but not actually understand. I think it's technically feasible, but that doesn't necessarily mean it's usable in that it is something the majority of the users can easily understand and like. |
I remember seeing @lrhn saying " I would argue that an expression Consider: void function({String value = 'default'}) {
print(value);
} then used this way: function(value: if (condition) 'hello world'); Then I think it would be logical for it to be an equivalent to: if (condition) {
function(value: 'hello world');
} else {
function();
} This means that if This also means that an "expression |
I can see how people would be mixed between both.
Say someone first defined |
@rrousselGit And as you say, if changing the function's type from An expression which evaluates to "nothing", like a missing else branch, can only meaningfully be used in a location where omitting something doesn't matter for the static typing. That's why it makes sense in a list, set or map literals - it's an arbitrary length repetition of things of the same type, so static typing is unaffected by omitting one of the entries. If we had rest parameters, it would make sense there too. |
Would it be possible to introduce a Then |
That means we could write: foo(nothing, 10) which means the first parameter gets its default value, and the second one is always This further means that: foo(if (cond) 42, 10) would be equivalent foo(if (cond) 42 else nothing, 10) which is consistent with collection ifs and named parameters |
Well, it's a keyword not a value. So since there's no added value in having |
These three language constructs are closely related:
I think the development of NNBD, which also introduces new syntax, offers an opportunity to merge the semantics and syntax.
Would it be possible to do something like this:
It seems to me that the first two points should be straightforward. All if-statements are now expressions. An if-expression with return type void is essentially an if-statement, this covers existing code.
The introduction of NNBD is probably very much needed for this feature, since an if-expression without an else block will return an optional value. So if the else branch doesn't exist, or if either branch returns a nullable type, the type of the if-expression is nullable.
Based on this, the ternary operator could be deprecated.
Well, I am aware that now my proposal breaks. Collection-ifs are now syntactically identical to an if-expression without an else block. And instead of filtering elements in the collection, they will insert lots of nulls.
As a fix, I would be happy with something like a 'remove-null' operator. Maybe
??
.So the code would look like this:
This language change would introduce if-expressions and merge the syntax of collection-ifs. Also, it would free up the syntax of the ternary operator, which could then be used for null checks. Actually, I think that the graceful deprecation of the ternary operator is the real advantage to be had here. This is directly related to #376
The text was updated successfully, but these errors were encountered: