Naetmul
Naetmul

Reputation: 15552

null to listOf(), not null to listOf(value) in Kotlin in one liner?

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?

Upvotes: 2

Views: 2059

Answers (2)

Nathan Reline
Nathan Reline

Reputation: 1227

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()
}

Upvotes: 6

Naetmul
Naetmul

Reputation: 15552

For this specific question, I can do

listOfNotNull(f())

Upvotes: 3

Related Questions