Let f()
return a nullable value.
What I want to do is that
if f()
is null, get an empty list,
else if f()
is not null, get a list of the single item value
.
In Scala, we can do something like this:
Option(f()).toList
or more verbosely
Option(f()).map(v => List(v)).getOrElse(List.empty)
In Kotlin, there is no Option
(assuming no Funktionale library), and null does not have toList()
unlike (None: Option
) in Scala.
We have the Elvis operator, but null will be inside the listOf()
function, so it will be
listOf(f() ?: /* What can I do here? */)
What we want for null is listOf(/*no argument */)
, but the Elvis operator requires an argument, so listOf(f() ?: )
will result in a compile error.
At least we can do
val v = f()
if (v == null) listOf() else listOf(v)
but it is a two liner.
Is there some expression for this?
Where I will use this expression is in the class's primary constructor default argument, so if it is not a one liner, it will be enclosed in brackets, so something like this:
class A(
val p1: List<V> = run {
val v = f()
if (v == null) listOf() else listOf(v)
},
val p2: ... = ...,
...)
This looks pretty ugly, isn't it?
EDIT
As @Naetmul pointed out, listOfNotNull(f())
is syntactically better to what I originally posted below, and also takes a variable number of arguments, for example
val myList = listOfNotNull(f(), g(), h())
will return a list of all the results that were not null.
I would use let
here.
val myList = f()?.let { listOf(it) } ?: emptyList()
Use a ?.
safe call on the return value of f()
, then use let
to run a code block. If f()
is null, it won't run this block of code, resulting in a null value. Then we use the ?:
elvis operator to fall back to an empty list.
Here it is broken up into several lines for a better understanding
val myValue = f()
val myList: List<Any>
if (myValue != null) {
myList = listOf(myValue)
} else {
myList = emptyList()
}