2021-01-27

How to properly zip (combine) the values of two nullables in Kotlin?

I wonder what would be an idiomatic approach in Kotlin to combine two optional (nullable) values.

A simple showcase would be

  // or some other type that might be null
  val x: Int? = "42".toIntOrNull()
  val y: Int? = "123".toIntOrNull()
  
  // make a Pair or null in case x and/or y are actually null
  // Pair might be actually a meaningful domain-specific product type instead
  val combined: Pair<Int, Int>? = ...

Obviously the classic imperative style approach would be to make some kind of an if-expression

if (x != null && y != null) x to y 
else null

While this approach isn't per se bad, I prefer expression style functions (instead of blocks) which I obviously can't use here as I need to refer to x and y twice.

A really ugly alternative would be to create a nested ?.let statement:

val combined: Pair<Int, Int>? =
    x?.let { fst -> y?.let { snd -> fst to snd } }

How would a generic implementation of this admittedly ugly function look like?

val combined: Pair<Int, Int>? = x.zipWith(y, ::Pair)


fun <T, U, R> T?.zipWith(other: U?, transform: (T, U) -> R): R?
  = this?.let { fst -> other?.let { snd -> transform(fst, snd) } }

What inspired me for the name of the function was actually definition in Project Reactor's Mono, the Definition in MonadZip @ Hoogle and Kotlin's own zip extension for collections

This does not really improve the former implementation but at least hides its ugliness into a reusable small utility function. It also uses the concept of zipping two contents of a Box found in other libraries, data types and programming languages

Is there a better approach for nullability combinations? Any comments on my thought process would also be appreciated!



from Recent Questions - Stack Overflow https://ift.tt/3qUxikV
https://ift.tt/eA8V8J

No comments:

Post a Comment