When I learned about Kotlin a few years ago, I was surprised to find that I couldn’t write a ? b : c, which is common in many other languages. Of course, I can use if (a) b else c instead, but it’s not neat.
After using Kotlin for a few years, I still think that the ternary operator should be supported. It’s the only obvious disadvantage I can think of (compared to Java).
I noticed this post, but it’s closed. Hope the ternery operator can be reconsidered.
I do like the C-based conditional ternary operator. But, there are actually more languages that do not support it - such as some recent ones (eg. Rust, Julia, Nim and Crystal) and older popular ones like Python and Lua. Scala which inspired some aspects of Kotlin also chose not to implement it either.
Yeah, I generally only use it for things that are not computed. Most often for choosing between 2 string resources for the UI based on a boolean such as this other function I have:
val Boolean.toYesNo: StringDesc get() = map(yes_label, no_label)
My two cents: As Kotlin uses ? to express nullability and has a ?: operator, the usual c ? a : b would not feel right. However, what makes the expression if (c) a else b slightly hard to read is that c is separated from a only via the closing parenthesis. We could improve this and make it more readable if we allowed dropping the parentheses and adding a then instead:
val z = if (c) a else b
val z = if c then a else b
It reads particularly better if expressions are long and need to be wrapped:
val z = if (someLongish < condition)
someLongishA()
else
someLongishB()
val z = if someLongish < condition
then someLongishA()
else someLongishB()
// Or:
val z =
if someLongish < condition
then someLongishA()
else someLongishB()
That has several minor disadvantages; but worse, it doesn’t look like Kotlin. Every other conditional in Kotlin uses parens — when, while/do…while, params to functions like require(), etc. Dropping them for this one case would be inconsistent and confusing.
Also: it gets very confusing if you need to nest conditions. And it doesn’t work so well for multi-way ifs:
if someLongish < condition
then someLongishA()
else if someOther < condition
then someLongishB()
else someLongishC()
(You could drop the indentation, but it’s still confusing having some else lines followed by conditions and others by values.)
I suppose you could keep the parens but allow then to be used — but does that give much benefit in the single-line case?
(Also, after almost 15 years, many people and organisations have significant investment in Kotlin code, so it’d have to be optional to avoid breaking existing code.)
Don’t break existing code. Make it optional. If you like the parentheses, you can still use them.
This is about the ternary operator. Your example is just a normal if statement. Of course, you could also use “then” there, but that’s off the point.
The ternary operator is confusing when using for nested conditions. See discussions on prettier for JavaScript/TypeScript. The least confusing formatting is IMO like this:
const r =
c1 ? a
: c2 ? b
: c3 ? c
: d;
Which could be written as:
// current Kotlin
val r =
if (c1) a
else if (c2) b
else if (c3) c
else d
// proposed syntax
val r =
if c1 then a
else if c2 then b
else if c3 then c
else d
I find the proposed syntax slighty better to read. But by all means make it optional.
Anyway, for nested ifs, it’s better to use when probably.
val r = when {
c1 -> a
c2 -> b
c3 -> c
else -> d
}
With other words, the ternary operator isn’t the best choice for situations that need nested condition checks, and Kotlin already has a when statement. The ternary operator is very handy for cases when a single if statement is inlined in an expression, and the existing if in Kotlin is just slightly harder to read IMO, but adding then could make improve it. But it’s a matter of taste, of course.
And yes, for consistency, it should then also be allowed to drop the paretheses with while and for loops. That doesn’t look like current Kotlin, but does that make it bad? (The only bad thing I see that it would create inconsistency in coding style across the community.)
Here’s a better example why I think then could improve the readability:
return if (a * x + b * y < c * z) (t - t0) * (q - p0)
else (t + t0) * (q - p1)
// Or
return if a * x + b * y < c * z then (t - t0) * (q - p0)
else (t + t0) * (q - p1)
// Or, since parentheses are optional in this proposal
return if (a * x + b * y < c * z) then (t - t0) * (q - p0)
else (t + t0) * (q - p1)
In the existing parentheses-based syntax, the place where the condition ends and the statement starts is not easily seen. Of course, you could add {} braces, but that forces newlines with some formatters.
This example also makes it clear that dropping the parentheses is not a big deal. The thing that makes it easier to read is the proposed optional then.
I guess this is just my opinion, but I think that a ternary is most valuable when the whole expression fits on one line. As soon as you start splitting it across multiple lines, imo an if expression looks better. idk if you’ve deliberately split it, or if that’s just how the forum has formatted it, but I would go all the way and fully separate it out, like so:
return if (a * x + b * y < c * z)
(t - t0) * (q - p0)
else
(t + t0) * (q - p1)