Kotlin has no ternary operator (conditional operator)

Kotlin and ternary operator (conditional operator)

With Google's official support for Kotlin as the Android development language, Kotlin has been a hot topic lately, but Kotlin doesn't have a ternary operator.

val max = a > b ? a : b // NG

Instead, Kotlin if is treated as an expression, so you can write:

val max = if (a > b) a else b

But isn't it inconvenient that Java has a ternary operator but Kotlin doesn't? : thinking_face: So this time, I'd like to force something like a ternary operator: muscle:

Define a ternary operator

You can't use Operator overloading because Kotlin doesn't have the operators ? And :.

However, you can use ʻinfix` to define your own operator (what looks like). https://kotlinlang.org/docs/reference/functions.html#infix-notation

This time, define the class and infix function as follows.

data class TernaryOperation<out T>(val condition: Boolean, val value: T)

infix fun <T> Boolean.`?`(other: T) = TernaryOperation<T>(this, other)
infix fun <T> TernaryOperation<T>.`:`(other: T) = if (this.condition) this.value else other

? And : cannot be used as function names, so they are enclosed in backticks. However, although I could use `?`, I couldn't use `:` for some reason, so I chose `:` (full-width). Also, in Kotlin, you can use Japanese for function names as in Java, but ? You cannot use oror:`.

It looks like this when using the function defined above.

val max = (a > b) `?` a `:` b

It feels like that: sweat_smile:

Difference from Java ternary operator

Operator priority

Kotlin's infix function has a higher priority than the comparison operator. https://kotlinlang.org/docs/reference/grammar.html#precedence

On the other hand, Java ternary operators have a lower priority than comparison operators. https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

Therefore, if you want to use a comparison operator, etc., like the ternary operator created this time, you need to enclose the conditional expression in parentheses.

Java


int max = a > b ? a : b; // OK

Kotlin


val max = a > b `?` a `:` b // NG

val max = (a > b) `?` a `:` b // OK
val max = (a > b) `?` a + 3 `:` b - 5 // OK

Evaluation of the formula

I noticed in the comment of saka1029. Thank you: bow:

Since the ternary operator mock created this time passes a value, both values will be evaluated regardless of the truth of the condition.

Java


int value = array.length > 0 ? array[0] : -1; // OK

Kotlin


val value = array.isNotEmpty() `?` array[0] `:` -1 //ArrayIndexOutOfBoundsException when array is empty

To avoid this, you have to make it ()-> T type instead of T type, but it is no longer different from if expression: sweat_smile:

data class TernaryOperation<out T>(val condition: Boolean, val value: () -> T)

infix fun <T> Boolean.`?`(other: () -> T) = TernaryOperation<T>(this, other)
infix fun <T> TernaryOperation<T>.`:`(other: () -> T) = if (this.condition) this.value() else other()

val value = array.isNotEmpty() `?` { array[0] } `:` { -1 } // OK

Patterns that use the Elvis operator

Define the following infix function.

infix fun <T> Boolean.then(other: T) = if (this) other else null

Using the Elvis operator, you can write it like a ternary operator as follows.

val max = (a > b) then a ?: b

However, if you use null for the value when true, it will always be the value when it is false: cry:

val body = response.isError() then null ?: response.body // always response.body

Also, as before, there are priority issues and expression evaluation issues.

Summary

I tried to make it with material, but it's still inconvenient: sweat: I also use Python a lot, so I'm still new to writing Kotlin ternary operators: sob:

If you have any impressions or opinions, please comment: bow:

Recommended Posts

Kotlin has no ternary operator (conditional operator)
Reference ternary operator
Ruby conditional branch. if, conditional operator (ternary operator), unless, case
Kotlin 1.3.50 has been released !!
About the ternary operator
A confused story about a ternary operator with multiple conditional expressions
Is the ternary operator evil?