Kotlin 2.5.0-Beta2 Adds Experimental onTrue, onFalse, and ifOrNull to Simplify If-Else
Kotlin keeps improving.
Kotlin 2.5.0-Beta2 provides three experimental standard library functions (already listed in the 2.5.0-Beta1 release notes):
onTrue()onFalse()ifOrNull()
They reduce repetitive if-else expressions and make some common Kotlin patterns easier to read.
I've noticed a small trend in modern languages: more support for chained call styles.
Below we use common Android scenarios to illustrate their usage.
1. onTrue() and onFalse()
What they do
Suppose we need to perform an action based on a Boolean result. For example:
- Login succeeded, log the success.
- Login failed, log the error.
- Payment succeeded, trigger an analytics event.
Typically, we'd write an if-else block to handle that.
Before: using if-else
There's an Android login screen. After verifying user credentials, we want to log whether authentication succeeded or failed.
fun authenticate(user: User, token: String): Boolean {
val isAuthenticated = verifyToken(user.email, token)
if (isAuthenticated) {
logSuccess("Login successful")
} else {
logFailure("Login failed")
}
return isAuthenticated
}
This code is fine and is something we're already used to.
Now: using onTrue() and onFalse()
@OptIn(ExperimentalStdlibApi::class)
fun authenticate(user: User, token: String): Boolean =
verifyToken(user.email, token)
.onTrue {
logSuccess("Login successful")
}
.onFalse {
logFailure("Login failed")
}
Doesn't this look a bit like how Result is handled?
How to understand them
onTrue():
- Only executes the lambda when the Boolean value is
true. - Does nothing when the value is
false. - Returns the original Boolean value.
onFalse():
- Only executes the lambda when the Boolean value is
false. - Does nothing when the value is
true. - Returns the original Boolean value.
For example:
@OptIn(ExperimentalStdlibApi::class)
val result = true
.onTrue { println("Success") }
.onFalse { println("Failure") }
println(result) // true
It's actually simple!
When should you use it? It depends on your preference and needs, but here are some scenarios:
- Log success or failure.
- Trigger analytics events.
- Show lightweight prompts.
- Invoke callbacks based on the result.
If you only need to perform an action based on a Boolean value and keep the original Boolean result, consider these two functions.
They suit side effects without converting the Boolean into something else.
2. ifOrNull()
What it does
Sometimes we want to return a value only when a condition holds, and null otherwise.
For example, a user profile page: users may or may not have filled in a phone number. We only want to provide the phone number if contact info exists.
Before: using if-else
val phoneNumber = if (user.hasContactInfo) {
user.phoneNumber
} else {
null
}
In Kotlin 2.5.0-Beta2, there's a shorter way.
Now: using ifOrNull()
@OptIn(ExperimentalStdlibApi::class)
val phoneNumber = ifOrNull(user.hasContactInfo) {
user.phoneNumber
}
How to understand it
You can think of ifOrNull() as a function that provides a value based on a condition:
- When the condition is
true, execute the lambda and return its result. - When the condition is
false, returnnull. - When the condition is
false, the lambda is not executed.
Real scenario: mapping API responses
Suppose in Android development, an API returns a user profile. Some users have contact info, some don't.
data class User(
val name: String,
val hasContactInfo: Boolean,
val phoneNumber: String?
)
We only want to prepare the phone number for the profile page when contact info exists.
@OptIn(ExperimentalStdlibApi::class)
fun getDisplayPhoneNumber(user: User): String? {
return ifOrNull(user.hasContactInfo) {
user.phoneNumber ?: "No phone number"
}
}
This way:
- When
hasContactInfoistrue, the lambda runs and returns the phone number or a fallback string. - When
hasContactInfoisfalse, the result isnull.
You can use this style when mapping API responses, preparing optional UI data, or creating DTOs.
3. Capability cheat sheet
| Function | Purpose | Return value |
|---|---|---|
onTrue() |
Runs an action when value is true |
The original Boolean value |
onFalse() |
Runs an action when value is false |
The original Boolean value |
ifOrNull() |
Runs a block when condition is true |
The block's result or null |
4. Still experimental
In Kotlin 2.5.0-Beta2, these functions are experimental APIs. You need to explicitly opt in:
@OptIn(ExperimentalStdlibApi::class)
You can also opt in uniformly with the compiler option -opt-in=kotlin.ExperimentalStdlibApi.
This article uses the Beta2 version as an example. Before adopting these APIs in production code, check the latest Kotlin documentation to confirm their status and usage.
5. Some thoughts
These three functions aren't big changes, but they make common Kotlin patterns more expressive. When you run into repetitive conditional blocks, you can directly state what you want to do:
- Run an action when successful: use
onTrue(). - Run an action when failed: use
onFalse(). - Return a value based on a condition: use
ifOrNull().
Of course, line count isn't the only goal. What matters more is making code easy to understand and maintain.
Also, as I mentioned at the start, modern languages increasingly favor chained calls. After writing one function call, I can naturally continue using . to call the next function to process the result. In these scenarios, this style is indeed more concise and flows better than using if-else.
Maybe that's one of the reasons RxJava was so popular back then.
Top 1 of 2 from juejin.cn, machine-translated. The original thread is authoritative.
You can just use extension functions to do that, the company project is still on 1.7.20.
Of course, this isn't necessary either.