Let's say I have an expensive function called doHardThings()
which may return various different types, and I would like to take action based on the returned type. In Scala, this is a common use of the match
construct:
def hardThings() = doHardThings() match {
case a: OneResult => // Do stuff with a
case b: OtherResult => // Do stuff with b
}
I'm struggling to figure out how to do this cleanly in Kotlin without introducing a temporary variable for doHardThings()
:
fun hardThings() = when(doHardThings()) {
is OneResult -> // Do stuff... with what?
is OtherResult -> // Etc...
}
What is an idiomatic Kotlin pattern for this common use case?
Local variables can be declared in two ways: first, with the val keyword, then they are immutable (the variable cannot be reassigned). If you are coming from Java, val would be equal to variables declared with a final keyword.
Kotlin does not require you to mention the type of a variable when declaring it (thanks to type inference). A variable val must be initialized in the same block of code in which it was declared. You can define a variable as being able to contain a null value using the question mark ? .
let takes the object it is invoked upon as the parameter and returns the result of the lambda expression. Kotlin let is a scoping function wherein the variables declared inside the expression cannot be used outside.
To declare a string in Kotlin, we need to use double quotes(” “), single quotes are not allowed to define Strings.
Update: this is now possible, from Kotlin 1.3. Syntax is as follows:
fun hardThings() = when (val result = doHardThings()) {
is OneResult -> // use result
is OtherResult -> // use result some other way
}
Old answer:
I think you'll just have to have a block body for the function and save the result of the operation to a local variable. Admittedly, this is not as neat as the Scala version.
The intended use of when
with is
checks is to pass in a variable and then use that same variable inside your branches, because then if it passes a check, it gets smart cast to the type it was checked for and you can access its methods and properties easily.
fun hardThings() {
val result = doHardThings()
when(result) {
is OneResult -> // result smart cast to OneResult
is OtherResult -> // result smart cast to OtherResult
}
}
You could write some sort of wrapper around your operation somehow so that it only evaluates it once and otherwise returns the cached result, but it's probably not worth the complications that it introduces.
Another solution for creating the variable by @mfulton26 is to use let()
:
fun hardThings() = doHardThings().let {
when(it) {
is OneResult -> // it smart cast to OneResult
is OtherResult -> // it smart cast to OtherResult
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With