Ternary operator


#1

Hello, please, add ternary operator


#2

Can you, please, elaborate with some use-cases. Some examples of your code would be really helpful.


#3

yes, something like this

 if (!response.isSuccessful()) {
        result = "fail"
 } else {
        result = response.body().string()
 }

 return result

and i think it would be better like this

return (!response.isSuccessful()) ? "fail" : response.body().string()

#4

I’d suggest you to consider using if expression in Kotlin. This is pretty idiomatic:

return if (!response.isSuccessful()) "fail" else response.body().string()

It becomes slightly better if you flip it:

return if (response.isSuccessful()) response.body().string() else "fail"

And you if are actually designing your own Kotlin API for response object, then you can make body() return null when response is not successful, and the usage is going to be even better with Kotlin’s elvis operator:

return response.body()?.string() ?: "fail"

#5
response.body()

is “never null” as documentation says.
another example is:

result = (!response.isSuccessful()) ? "fail" : response.body().string()

because i have to add some things like:

response.close()

before i

return result

i thought to write something like this:

result = if (!response.isSuccessful()) "fail" else response.body().string()

and it is ok, but it looks verbose


#6

If you happen to find yourself writing this kind of code often, then you can consider defining an extension function like this one for the corresponding Response class (whatever it is the actual class you are using):

fun Response.bodyOrNull(): Body? = if (isSuccessful()) body() else null

with this extension function your code reduces to

return response.bodyOrNull()?.string() ?: "fail"

#7

i suppose it is useful to write the extension function if i would use it many times. But in this case it looks redundant, since i wrote

if (!response.isSuccessful()) "fail" else response.body().string()

only in one method


#8

I think your idea (bodyOrNull) is only useful in some special cases. The purpose of ternary operator is for more general cases. The main advantage of using ternary operator is making code concise when the logic is short. This kind of logic happens very often in real life. Let’s compare these 2 versions:

val v = if (b) x else y // 23 chars
val v = b ? x : y // 17 chars (saved 6 chars = 26%)

In the case of @edgeone:

result = if (response.isSuccessful()) response.body().string() else "fail" //74 chars
result = response.isSuccessful() ? response.body().string() : "fail" //68 chars (saved 6 chars = 8%)

IMO, saving 26% of time for typing in first case is really a good deal, plus the code in 2nd line is very clean and easier to read. For the later, we can only save 8% of time. If the expression is longer, it would be better to use if/else and separate into multiple lines to improve code readability.

I am really wonder why Kotlin doesn’t support this feature. The goal of Kotlin is to be better than Java, but in this case, it is not.


#9

Writing code with the least number of characters is definitely non-goal for Kotlin.


Why is slice a possible language future feature?
#10

Of course, we must always check for other perspectives. Therefore I asked: “why Kotlin doesn’t support this feature?”

If the feature is only a good thing, does not prevent other features and used commonly, then it should be supported (or at least plan to do it if it is not yet so important).
In the case of “optional semicolons”, Kotlin has the right decision because it saves developers’ time and make them happy. Ternary operator will also do the same job.


#11

I think that this page gives a pretty exhaustive answer on this question: https://kotlinlang.org/docs/reference/control-flow.html

In Kotlin, if is an expression, i.e. it returns a value. Therefore there is no ternary operator (condition ? then : else), because ordinary if works fine in this role.


#12

I believe Kotlin lacks ternary conditional operator because it was impossible to get it into the grammar at the point the language was designed. For example, colon : was used to do static type assertion:
val c = someList: Collection // now c is Collection<T>

That syntax was removed before 1.0, but I’m not sure is there any syntactical obstacles left for ternary conditional operator.


#13

@elizarov: the reason in kotlin docs does not really convince me :slight_smile:
@ilya.gorbunov: “static type assertion” you mentioned is a good reason, IMO.


#14

Total unnecessary nitty gritty side-note: Can we please call this thing “conditional operator” or “conditional ternary operator”, but not “ternary operator”? Thank you! :blush:


#15

I usually use “conditional operator”, but most people like the term “ternary operator” :smile:


#17

#18

Ternary shorthand doesn’t seem useful in Kotlin since Kotlin’s if/else is already an expression.

At best, it saves a whole four characters at the expense of adding more syntax to the language. Or it ever-so-slightly increases the brevity of code that was already trivial to begin with.

It’s nice in a language like Javascript when if/else is a statement and rather unwiedly

Frankly, I think this sort of error handling is best done with a short-circuit rather than branching it against the success case.

if (!response.isSuccessful()) return "fail"
return response.body().string()

Especially since, as you point out, tend to need more logic in the success path.

(Couldn’t pass up a good bike-shedding opportunity)


#19

i think, the bigger any project will be, the more one will need to write if/else, and because of that, in a strategic point of view it looks like it would be better to add a ternary operator in the compiler


#20

Care to elaborate?


#21

implementing a ternary operator in the compiler is a task what will be done once.
Writing if/else instead of a ternary operator in each project will cost more than adding a ternary operator.