Loic
Loic

Reputation: 3370

How to compose nullables in Kotlin

Let's imagine you have 2 fonctions returning nullable and you cant to compose this 2 functions :

fun giveInt(x: Int):Int? = x+1
fun giveInt2(x: Int):Int? = x+2

To achieve the composition, I wrote this functions :

fun all(x:Int):Int? {
  val y = giveInt(x)
  if (y != null) return giveInt2(y) else return null;
}

val four = all(1)

Is it possible to compose 2 nullable values to get another nullable without explicitly writing if (y != null) and return null?

In Scala I would just do something like :

def giveInt(x: Int):Option[Int] = Some(x+1)
def giveInt2(x: Int):Option[Int] = Some(x+2)
def all(x:Int): Option[Int] = giveInt(x).flatMap(giveInt2)

Should I use java Optional to achieve this or is it possible with ? operator?

Thanks :)

Upvotes: 3

Views: 1209

Answers (3)

Luca Piccinelli
Luca Piccinelli

Reputation: 399

the answer of voddan is ok when you have only two nullables, but doesn't scale well on many nullables or in complicated use-case. For these situations there exist Konad library that handles multiple nullables as follows:

val foo: Int? = 1
val bar: String? = "2"
val baz: Float? = 3.0f

fun useThem(x: Int, y: String, z: Float): Int = x + y.toInt() + z.toInt()

val result: Int? = ::useThem.curry() 
   .on(foo.maybe) 
   .on(bar.maybe) 
   .on(baz.maybe)
   .nullable

if you want to keep it nullable, or

val result: Result<Int> = ::useThem.curry() 
   .on(foo.ifNull("Foo should not be null")) 
   .on(bar.ifNull("Bar should not be null")) 
   .on(baz.ifNull("Baz should not be null"))
   .result

if you want to accumulate errors. See maybe section

Upvotes: 0

voddan
voddan

Reputation: 33769

In case you want to literally compose two functions (in the FP sense), then it is better to use function references for readability:

fun giveInt(x: Int):Int? = x+1
fun giveInt2(x: Int):Int? = x+2

fun all(x: Int): Int? = giveInt(x)?.let(::giveInt2)

Upvotes: 3

erkangur
erkangur

Reputation: 2128

It is possible with safe call ?. operator and let function combo like this:

fun giveInt(x: Int):Int? = x+1
fun giveInt2(x: Int):Int? = x+2

fun all(x: Int): Int? = giveInt(x)?.let { giveInt2(it) }

For more idioms like this, use this link.

Upvotes: 6

Related Questions