Guard Condition in when — Kotlin 2.1.0
Kotlin 2.1.0 introduces a new feature guard conditions in when expressions or statements with subjects.
The guard condition allows the inclusion of more than one condition for the branches of a when expression, flattening the code structure and making the complex flow more explicit and concise.
Place a guard condition in a branch after the primary condition, separated by if.
when (<subject>) {
// only the primary condition.
<primary-condition1> -> {
// primary condition 1 satisfied action.
}
// Branch with both primary and guard conditions.
<primary-condition2> if <guard condition1> -> {
// primary condtion 2 and guard condition satisfied action.
}
// Branch if none of the above primary/guard conditions match.
else if <guard condition2> -> {
// action for guard condition 2 being satisfied.
}
// If none of the above conditions match.
else -> {
// action for none of the conditions matching.
}
}
The guard condition is not evaluated if the primary condition does not match. The code in the branch is only executed if both the primary and guard conditions are considered true.
It is possible to combine multiple guard conditions into a single branch using &&
and ||
operators.
when (<subject>) {
// Branch with both primary and guard conditions.
<primary-condition> if ((<guard condition1> && <guard condition2>) || <guard condition3> ) -> {
// primary condtion and guard conditions satisfied action.
}
}
Example
The guard condition can be used to simplify/flatten out the parsing of the response of REST API.
Let’s assume we have the following classes and methods for fetching and handling data from a remote server using a REST API.
public sealed interface NetworkResponse
public class ResponseSuccess(public val data: String) : NetworkResponse
public class ResponseFailure(public val errorCode: Int, public val errorMessage: String) :
NetworkResponse
class RemoteRepository {
fun fetchData(): NetworkResponse {
// fetches data from remote server
}
}
To parse the response without the guard condition, the code would look something like
when(response) {
is ResponseSuccess -> {
}
is ResponseFailure -> {
val errorCode = response.errorCode
if (errorCode == 501) {
// do nothing
} else if (errorCode == 401) {
// reauthorize
} else {
// retry
}
}
}
With guard condition, it could be written as follows
when(data) {
is ResponseSuccess -> {
}
is ResponseFailure if (data.errorCode == 501)-> {
// do nothing
}
is ResponseFailure if (data.errorCode == 401)-> {
// reauthorize
}
else -> {
// retry
}
}
From the functionality point of view, the guard condition does not have anything additional. It improves the readability of the code.
Note: Response code handling is only for representational purposes and might not be the best way to handle response codes.
Currently, the guard condition feature is experimental. To enable the feature, use the following compiler option.
kotlinc -Xwhen-guards main.kt
To enable the feature in your Gradle file, add the flag in the compilerOptions block as follows.
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xwhen-guards")
}
}