Is it possible to make the following code to compile in Kotlin?
val variable: String? = "string"
val (a, b) = variable?.run {
1 to 2
}
Is it possible to make the following code to compile in Kotlin?
val variable: String? = "string"
val (a, b) = variable?.run {
1 to 2
}
The compiler does not allow destructuring because the expression on the right-hand side is typed as a nullable Pair<Int, Int>?
, and it's unclear what values a
and b
should get in case variable
is null.
To solve this, you need to get a not-null expression after =
.
There's a lot of different ways to deal with nullable values and produce a not-null value from a nullable one, see: In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them
For example, if you want to provide fallback values for a
and b
, then use the ?:
operator as follows:
val (a, b) = variable?.run {
1 to 2
} ?: (0 to 0)
An alternative, for example, would be to check variable
for null first:
val (a, b) = checkNotNull(variable) { "variable should never be null" }.run {
1 to 2
}
Null doesn't have any destructuring declarations. If you want a value of null to destructure like it's a pair of nulls, you could add these extensions:
operator fun <T> Pair<T, *>?.component1() = this?.component1()
operator fun <T> Pair<*, T>?.component2() = this?.component2()
Otherwise, as the other answer shows, you need to provide a default using the Elvis operator.
It's not automatic because it doesn't know what you want. Depending on what you're doing with it, 0 to 0
may be most appropriate, or maybe -1 to -1
or 0 to null
or null to null
.
The question is, what do you want to do if your variable is null? If you want to throw an exception, go with require
or check
as @hotkey suggested.
However I have the case where I just want to return if the value is null. So I wrote myself a little helper function that allows for this:
private inline fun <T> T?.exitIfNull(exitBlock: () -> Nothing): T {
if (this == null)
exitBlock()
else
return this
}
You can call this function as follows:
val (a, b) = variable?.run {
1 to 2
}.exitIfNull {
return
}
A nice little use of the Nothing
keyword in Kotlin that I personally find quite fascinating