ceylon
ceylon copied to clipboard
make 'then' optional in 'if' expressions?
In practice, I think I find then in if expressions significantly more annoying than I thought I would. And I've heard at least some complaints about it. The reason for requiring then was:
- symmetry of the two branches of the
if, and - to help resolve a grammatical ambiguity with the syntax of comprehensions.
I now no longer care about 1. I do still care about 2, but I must admit that we use comprehensions much less than I expected, and if expressions much more, so I guess I'm prepared to sacrifice some convenience in comprehensions in order to get a little convenience in if expressions. (It's somewhat a tough call, however.)
The issue with comprehensions is the interpretation of the following code:
for (x in xs) if (fun(x)) x else 0
Does this mean:
for (x in xs) if (fun(x)) (x else 0)
Or:
for (x in xs) (if (fun(x)) x else 0)
The requirement for then neatly resolved that ambiguity in favor of the first interpretation. However, there was always the option of resolving it in the opposite direction, interpreting (if (fun(x)) x else 0 as an if expression instead of a clause of the comprehension.
The way to do that is to specify that the expression clause of a comprehension is not a full expression, but rather what the grammar calls a conditionalBranch. You can write almost any expression in a conditionalBranch except:
- anonymous functions
then/elseoperators- assignments
switchexpressions
Currently the branches of an if, switch, or let are conditionalBranches, but the expression clause of a comprehension is a full functionOrExpression.
So what this boils down to is, if I recall everything correctly:
- we could let you leave out the
thenin anifexpression, - but only if we required you to put parens around anonymous functions, the
elseoperator, andswitches in the expression clause of a comprehension.
Is there any support here for making a change like that?
To be clear: this change described would break some perfectly-reasonable code.
I like the expressiveness of then, alot. To me, it's much easier to read third party code, if I can immediately distinguish different parts of code due to that explicity.
Note: if I don't hear lots of expressions of support for making this change, I'm not going to do it :-)
I like that its syntax reminisces the if statement more. If then in the if statement isn't required/allowed, why should it be required in the if expression? Removing the then makes it clearer that one syntax is derived from the other, instead of introducing a keyword that syntactically separates the two semantically related constructs.
That is, I would like the then keyword in if expressions if if statements also were written with then:
if(is String foo)
then {
// do something
}
else {
// do something
}
But since it isn't, for symmetry with if statements, I think if expressions should not have a then either.
Further, I feel like @gavinking's first reason predicts that if expressions would be written in multiple lines as the following:
if(exists foo)
then foo.string
else "null"
In practice, however, I've mostly seen them written in multiple lines similar to how if statements are, as the following:
if(exists foo) then
foo.string
else
"null"
Which invalidates the first reason for then.
Well, your example could easily be rewritten like this:
foo?.string else "null"
Much simpler imho.
Actually, why not make the brackets optional in this case (if it isn't already), instead of the then keyword? Less to type and more readability.
I am agree with @gavinking , I found then a little bit annoying.
For very short if expressions there are so many words.
value a = if(a % 2 == 0) then zero else one;
And then word in this example isn't necessary
I don't find then annoying, but to resolve grammatical ambiguity without it ; may be you can inverse order of if :
instead of value a = if(a % 2 == 0) then zero else one;
you could have :
value a = zero if(a % 2 == 0) one else;
And
for (x in xs) x if (fun(x)) 0 else
is clearly not the same as
for (x in xs) x else 0 if (fun(x))
@luolong
Well, your example could easily be rewritten like this
Yeah, sure, but it was just an example. I could easily be trying to access a member that can be null too, and so wouldn't be able to use ?..
@ChristopheLs , no no no , in the inverse order so hard to make conclusions on quick look.
I used something similar in ruby (example a = :zero if a % 2 == 0), but in later i rewrote all this places in common order.
In this place i prefer regularity. Good example in golang - unified form of cycle and control structures.
For the record. I like ‘then’ and ‘else’ in if expressions. Much regular. Plus it affords nice formatting:
value v = if (someBooleanExpression())
then someValueExpression()
else alternativeExpression();
@luolong, I don't understand why you think it's more regular since if statements don't have a then. I'd love if you could elaborate.
On the formatting, have you considered writing it as the following?
value v = if(someBooleanExpression())
someValueExpression()
else
alternativeExpression();
@Zambonifofex Regarding regularity, I am not really talking about making if statement syntax similar to if expression. This is not the regularity I am looking for.
(they are different syntactic elements and I am okay with them having different syntax -- less likely to get mixed up that way)
The regularity I am talking about is internal to the if expression. I like that the if expression consists of three components (predicate expression, if true expression and if false expression). and each component has a keyword associated with it -- makes it easy to parse (for humans that is) and easy to format.
If anything I would look at deprecating then expression. (The else expression is still useful in many places, so I would keep that)
Regarding your formatting choice, I don't much like it unfortunately. There was something about using then keyword that encourages short and descriptive expressions (they have to fit on one line after all), while the one without then, with the formatting you proposed looks like it invites longer indented expressions, spanning multiple lines. But it might just be me.
Now I do realise that in very short if expressions, the then and else pair can get sort of cumbersome. But I don't think it is not all that bad...
value v = if (affirmative) then "yes" else "no";
In the end, I don't think we have any really good reasons (yet) to drop then keyword from if expression. Maybe if we figure out how to measure price developers pay for wrong or inconvenient syntax, we could use that data to drive such a decision. I doubt we get much support from data though.
@luolong
The regularity I am talking about is internal to the if expression. I like that the if expression consists of three components (predicate expression, if true expression and if false expression). and each component has a keyword associated with it -- makes it easy to parse (for humans that is) and easy to format.
That's fine, but I don't think I'd call that "regularity". Regularity is about consistency with the rest of the language, and about how well something fits in, not about how well something works by itself.
Either way, I really can't agree with what you said; I feel like the if and condition list are the "keyword" to the true-expression, and the else is the keyword to the false-expression -- just as they each are keywords to each block in if statements. For example, I've seen people formatting if expressions as the following, which suggests that mindset:
if(foo) then
bar
else
baz
Let's not digress into formatting flame war!
So far it doesn't look like we have a single person who supports making this change!
@gavinking, I do!
I am another one
o/
I support leaving it as if-then-else.
Please, use the +1 or -1 reaction directly below the first post to express your opinion in a way, that's easy to count. :)
I apologize for this, but if it wasn't so radical a change, I would propose a new keyword iff (or something similar) for comprehensions, and then get rid of then:
BEFORE:
for (x in xs) if (fun(x)) then x else 0
for (x in xs) if (fun(x)) (x else 0) // final parenthesis optional
AFTER:
for (x in xs) if (fun(x)) x else 0
for (x in xs) iff (fun(x)) x else 0
I dislike iff a bit for being so visually similar to if, please suggest better alternatives..
Motivation: "iff" == "if and only if", attempting to communicate the filtering capacity of the keyword.
What about this case then, does it make it any clearer/better?
BEFORE:
for (x in xs) if (fun1(x)) if (fun2(x)) then x else 0
AFTER:
for (x in xs) iff (fun1(x)) if (fun2(x)) x else 0