๐ŸŽ“ A1Learner
๐Ÿ”
0 of 37 lessons completed

Kotlin With and TakeIf

with runs a block with a value as the receiver, and takeIf keeps a value only when a test passes. A failed takeIf test gives null.

with returns a block value

The crate is the receiver of the block. The block returns twice the item count.

class Crate(val name: String, val items: Int)

fun main() {
    val crate = Crate("books", 9)
    val doubled = with(crate) {
        println(name)
        items * 2
    }
    println(doubled)
}

takeIf passing and failing

The first age passes the test and stays. The second age fails the test and becomes null.

fun main() {
    val adult = 20.takeIf {
        it >= 18
    }
    println(adult)
    val child = 12.takeIf {
        it >= 18
    }
    println(child)
}

takeUnless keeps on failure

takeUnless drops a score when the test passes. A low score is dropped, and a high score stays.

fun main() {
    val low = 45.takeUnless {
        it < 50
    }
    println(low)
    val high = 80.takeUnless {
        it < 50
    }
    println(high)
}

takeIf with the Elvis operator

An empty name fails the test, so the Elvis operator supplies a fallback. A real name passes and stays.

fun main() {
    val name = "".takeIf {
        it.length > 0
    } ?: "guest"
    println(name)
    val city = "Oslo".takeIf {
        it.length > 0
    } ?: "unknown"
    println(city)
}

Example

class Account(val owner: String, val balance: Int)

fun main() {
    val account = Account("Mira", 120)
    val label = with(account) {
        "$owner has $balance"
    }
    println(label)
    val large = account.balance.takeIf {
        it >= 100
    } ?: 0
    println(large)
}

Key points

  • with takes the receiver as its first argument.
  • Inside a with block, members of the receiver are read directly.
  • with returns the value of the last expression in its block.
  • takeIf returns the value when its test passes.
  • takeIf returns null when its test fails.
  • takeUnless is the mirror of takeIf, and it keeps the value when its test fails.

In this example, with reads the owner and the balance of the account to build a label. takeIf keeps the balance because it reaches 100. The Elvis fallback of 0 is not needed.

Note

The Elvis operator can replace a null from takeIf with a fallback value.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Kotlin Playground

Exercise

What does 12.takeIf { it >= 18 } give?