How do you keep your code functionnal with nullabl...
# getting-started
j
How do you keep your code functionnal with nullables? For example:
Copy code
val list: List<Int> = listOf(1,2,3)

list
    .firstOrNull()
    ?: -1
    .toString()
    .padStart(2, '0')
I would like to apply
.toString().padStart(2, '0')
to the result of
list.firstOrNull() ?: -1
. But, due to Kotlin's precedence, it is only applied to
-1
.
this is a crafted example to help comprehension, but if you want to see the real code I'm stubbling one, here it is
s
The simplest and most general answer is probably brackets:
Copy code
(list.firstOrNull() ?: -1)
    .toString()
    .padStart(2, '0')
thank you color 1
👆 2
For a list, you can also use
getOrElse(0) { ... }
1
c
Usually, I use this as a signal that an intermediate variable would make the code clearer:
Copy code
val first = list
    .firstOrNull()
    ?: -1

first.toString()
    .padStart(2, '0')
👍 1
thank you color 1
j
Actually, that's what I went with. I hoped there would be something a bit more chainable, but I will keep the intermediate variable 🙂
Thanks to both of you!
🙏 1
j
list .firstOrNull() .let{it ?: -1} .toString() .padStart(2, '0)
plus1 1
K 1
j
oh, good idea!
c
I'm not a fan. I tend to avoid using
let
everywhere.
j
In this example I find it quite readable But I can't use it in my library code, it would be difficult to read in this case
y
You can define something like:
Copy code
inline fun <T: Any> T?.ifNull(replacement: () -> T) = this ?: replacement()
c
Most readable would probably be to define
firstOr(X)
then you have
Copy code
list
    .firstOr(-1)
    .toString()
    .padStart(2, '0')
Lots of standard library functions have
orNull()
variants so as to not throw exceptions. I wonder if a more general
or()
version in those contexts would be useful (as well as the null version). There's always
:?
or other functions to deal with the null version but if ultimately you're looking for a default then it's just extra noise.