Kotlin: Kotlin Ternary Conditional Operator

Kotlin Programming

Question or issue of Kotlin Programming:

What is the equivalent of this expression in Kotlin?

a ? b : c

This is not valid code in Kotlin.

How to solve this issue?

Solution no. 1:

In Kotlin, if statements are expressions. So the following code is equivalent:

if (a) b else c

The distinction between expression and statement is important here. In Java/C#/JavaScript, if forms a statement, meaning that it does not resolve to a value. More concretely, you can’t assign it to a variable.

// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c

If you’re coming from a language where if is a statement, this might seem unnatural but that feeling should soon subside.

Solution no. 2:

TL;DR
if (a) b else c

^ is what you can use instead of the ternary operator expression a ? b : c which Kotlin syntax does not allow.


In Kotlin, many control statements, such as if, when, and even try, can be used as expressions. As a result, these statements can have a result which may be assigned to a variable, be returned from a function, etc.

Syntactically, there’s no need for ternary operator

As a result of Kotlin’s expressions, the language does not really need the ternary operator.

if (a) b else c

is what you can use instead of the ternary operator expression a ? b : c.

I think the idea is that the former expression is more readable since everybody knows what ifelse does, whereas ? : is rather unclear if you’re not familiar with the syntax already.

Nevertheless, I have to admit that I often miss the more convenient ternary operator.


Other Alternatives

when

You might also see when constructs used in Kotlin when conditions are checked. It’s also a way to express if-else cascades in an alternative way. The following corresponds to the OTs example.

when(a) {
    true -> b
    false -> c
}

Extensions

As many good examples (Kotlin Ternary Conditional Operator) in the other answers show, extensions can also help with solving your use case.

Solution no. 3:

You could define your own Boolean extension function that returns null when the Boolean is false to provide a structure similar to the ternary operator:

infix fun  Boolean.then(param: T): T? = if (this) param else null

This would make an a ? b : c expression translate to a then b ?: c, like so:

println(condition then "yes" ?: "no")

Update:
But to do some more Java-like conditional switch you will need something like that

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

println(condition then { "yes" } ?: "no")
pay attention on the lambda. its content calculation should be postponed until we make sure condition is true

This one looks clumsy, that is why there is high demanded request exist to port Java ternary operator into Kotlin

Solution no. 4:

For myself I use following extension functions:

fun T?.or(default: T): T = if (this == null) default else this 
fun T?.or(compute: () -> T): T = if (this == null) compute() else this

First one will return provided default value in case object equals null. Second will evaluate expression provided in lambda in the same case.

Usage:

1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }

Personally for me code above more readable than if construction inlining

Solution no. 5:

Java’s equivalent of ternary operator

a ? b : c

is a simple IF in Kotlin in one line

if(a) b else c


there is no ternary operator (condition ? then : else), because
ordinary if works fine in this role.

https://kotlinlang.org/docs/reference/control-flow.html#if-expression


Special case for Null comparison

you can use the Elvis operator

if ( a != null ) a else b
// equivalent to
a ?: b

Solution no. 6:

Some corner cases not mentioned in other answers.

Since appearance of takeIf in Kotlin 1.1 the ternary operator a ? b : c can also be expressed like this:

b.takeIf { a } ?: c

This becomes even shorter in case c is null:

b.takeIf { a }

Also note that typical in Java world null checks like value != null ? value : defaultValue translate in ideomatic Kotlin to just value ?: defaultValue.

Similar a != null ? b : c can be translated to a?.let { b } ?: c.

Solution no. 7:


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. manual source from here

// Traditional usage 
var max = a 
if (a < b) max = b

// With else 
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}

// As expression 
val max = if (a > b) a else b

Solution no. 8:

There is no ternary operator in kotlin, as the if else block returns value

so, you can do:
val max = if (a > b) a else b
instead of java’s max = (a > b) ? b : c

We can also use when construction, it also return value:

val max = when(a > b) {
    true -> a
    false -> b
}

Here is link for kotlin documentation : Control Flow: if, when, for, while

Solution no. 9:

Take a look at the docs:


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.

Solution no. 10:

TASK:

Let’s consider the following example:

if (!answer.isSuccessful()) {
    result = "wrong"
} else {
    result = answer.body().string()
}
return result

We need the following equivalent in Kotlin:


return ( !answer.isSuccessful() ) ? “wrong” : answer.body().string()

SOLUTION 1.a. You can use if-expression in Kotlin:

return if (!answer.isSuccessful()) "wrong" else answer.body().string()

SOLUTION 1.b. It can be much better if you flip this if-expression (let’s do it without not):

return if (answer.isSuccessful()) answer.body().string() else "wrong"

SOLUTION 2. Kotlin’s Elvis operator ?: can do a job even better:

return answer.body()?.string() ?: "wrong"

SOLUTION 3. Or use an Extension function for the corresponding Answer class:

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

SOLUTION 4. Using the Extension function you can reduce a code thanks to Elvis operator:

return answer.bodyOrNull()?.string() ?: "wrong"

SOLUTION 5. Or just use when operator:

when (!answer.isSuccessful()) {
    parseInt(str) -> result = "wrong"
    else -> result = answer.body().string()
}

Solution no. 11:

Java

int temp = a ? b : c;

Equivalent to Kotlin:

var temp = if (a) b else c

Solution no. 12:

when replaces the switch operator of C-like languages. In the simplest form it looks like this

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither 1 nor 2")
    }
}

Solution no. 13:

There is no ternary operator in Kotlin. It seems problematic at the first glance. But think we can do it with inline if else statement because this is expression here. Simply we have to do –

var number = if(n>0) "Positive" else "Negetive"

Here we can else if block too as many as we need. Like-

var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"

So this line is so simple and much readable than ternary operator. when we use more than one ternary operator in java it seems horrible. But here we have a clear syntax. even we can write it in multiple line too.

Solution no. 14:

You can use var a= if (a) b else c in place of the ternary operator.

Another good concept of kotlin is Elvis operater. You don't need to check null every time.

val l = b?.length ?: -1

This will return length if b is not null otherwise it executes right side statement.

Solution no. 15:

as Drew Noakes quoted, kotlin use if statement as expression,
so Ternary Conditional Operator is not necessary anymore,

but with the extension function and infix overloading, you could implement that yourself, here is an example

infix fun  Boolean.then(value: T?) = TernaryExpression(this, value)

class TernaryExpression(val flag: Boolean, val truly: T?) {
    infix fun  or(falsy: T?) = if (flag) truly else falsy
}

then use it like this

val grade = 90
val clazz = (grade > 80) then "A" or "B"

Solution no. 16:

Another interesting approach would be to use when:

when(a) {
  true -> b
  false -> b
}

Can be quite handy in some more complex scenarios. And honestly, it's more readable for me than if ... else ...

Solution no. 17:

You can do it many way in Kotlin

  1. Using if

    if(a) b else c
    
  2. Using when

    when (a) { 
        true -> print("value b") 
        false -> print("value c") 
        else -> {  
            print("default return in any other case") 
        } 
    }
    
  3. Null Safety

    val a = b ?: c
    

Solution no. 18:

There is no ternary operation in Kotlin, but there are some fun ways to work around that. As others have pointed out, a direct translation into Kotlin would look like this:

val x = if (condition) result1 else result2

But, personally, I think that can get a bit cluttered and hard to read. There are some other options built into the library. You can use takeIf {} with an elvis operator:

val x = result1.takeIf { condition } ?: result2

What is happening there is that the takeIf { } command returns either your result1 or null, and the elvis operator handles the null option. There are some additional options, takeUnless { }, for example:

val x = result1.takeUnless { condition } ?: result2

The language is clear, you know what that's doing.

If it's a commonly used condition, you could also do something fun like use an inline extension method. Let's assume we want to track a game score as an Int, for example, and we want to always return 0 if a given condition is not met:

inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this     

Ok, that seems ugly. But consider how it looks when it is used:

var score = 0
val twoPointer = 2
val threePointer = 3

score += twoPointer.zeroIfFalse { scoreCondition } 
score += threePointer.zeroIfFalse { scoreCondition } 

As you can see, Kotlin offers a lot of flexibility in how you choose to express your code. There are countless variations of my examples and probably ways I haven't even discovered yet. I hope this helps!

Solution no. 19:

Remember Ternary operator and Elvis operator hold separate meanings in Kotlin unlike in many popular languages. Doing expression? value1: value2 would give you bad words by the Kotlin compiler, unlike any other language as there is no ternary operator in Kotlin as mentioned in the official docs. The reason is that the if, when and try-catch statements themselves return values.

So, doing expression? value1: value2 can be replaced by


val max = if (a > b)
print("Choose a")
else
print("Choose b")

The Elvis operator that Kotlin has, works only in the case of nullable variables ex.:


If I do something like value3 = value1 ?: value2 then if value1 is null then value2 would be returned otherwise value1 would be returned.

A more clear understanding can be achieved from these answers.

Solution no. 20:

If you do not what to use the standard notation you can also create/simulate it using infix with something like this:

create a class to hold your target and result:

data class Ternary(val target: T, val result: Boolean)

create some infix functions to simulate a ternary operation

infix fun  Boolean.then(target: T): Ternary {
    return Ternary(target, this)
}

infix fun  Ternary.or(target: T): T {
    return if (this.result) this.target else target
}

Then you will be able to use it like this:

val collection: List = mutableListOf(1, 2, 3, 4)

var exampleOne = collection.isEmpty() then "yes" or "no"
var exampleTwo = (collection.isNotEmpty() && collection.contains(2)) then "yes" or "no"
var exampleThree = collection.contains(1) then "yes" or "no"

Hope this helps!