Kotlin has no ternary operator because if returns a value: val fee = if (member) 0.0 else 4.99. when replaces switch, with no fall-through. With a subject it matches constants, ranges (in 1..5) or types (is String, smart-cast in the branch); without one, it tests Boolean conditions in order. A guard condition, stable since Kotlin 2.2, adds if to a branch of a when with a subject.
fun badge(book: Book): String = when {
!book.inStock -> "sold out"
book.rating >= 4.6 -> "top rated"
book.price < 17.0 -> "bargain"
else -> "-"
}
fun describe(x: Any): String = when (x) {
is String if x.isBlank() -> "blank text" // guard condition (Kotlin 2.2+)
is String -> "text of length ${x.length}"
is Int if x in 1..5 -> "a star rating"
else -> "something else"
}
fun main() {
println(catalog.map { "${it.title.substringAfterLast(' ')}: ${badge(it)}" })
println(listOf(" ", "Salt", 4, 9).map(::describe))
}Output
[Harbor: top rated, Web: -, Saffron: sold out, Summits: -, Paradox: bargain, Glass: -] [blank text, text of length 4, a star rating, something else]
As an expression, every path must produce a value, and the compiler enforces it:
val inStock = true
val label = if (inStock) "Add to cart"Output
NoElse.kt:2:13: error: 'if' must have both main and 'else' branches when used as an expression.
val label = if (inStock) "Add to cart"
^^A when over an enum, a Boolean or a sealed type needs no else once every case is covered, which keeps the sealed UI states of UI State with Sealed Classes safe to extend.