As you all know, Kotlin has a great null-safe type library. It’s unique in Java world. It was a huge effort to design, implement and polish the whole thing:
- It is completely safe and has magnificent IDE support
- It is extremely simple to learn and use - it has nearly-zero menal overhead
- It is as fast as possible in JVM with zero runtime overhead
- It just works.
Imagine a new developer who wants to learn Kotlin. One of the most common programming exercises is to reverse the string. Let’s open IDEA and type in this simple code:
val something = "ABC"
print( something.reverse() )
It looks good, sounds reasonable, compiles and runs. IDE support! Type inference! Null-safety! Sweet Kotlin.
The program prints ABC instead of CBA. Surprise!
In desperate panic, the first line gets changed a little bit:
val nothing = null
print( nothing.reverse() ) // what the f… function is called here?
It looks bad and sounds crazy. Nevertheless the program still compiles, runs and prints… null
Why is it allowed to use simple dot with nullable variable? Where is my NPE then? Null-safety magic? Is it my coffe or other exotic cultures?..
The truth is, there’s no reverse() method for String at all. Surprise!
At this moment our brave but unfortunate ealy adopter uninstalls IDEA and open his blog to spread his strong feelings.
It turns out that there is no “if” statement in Haskell (for Great Good).
Therefore, well-educated Haskell programmers have to use empty collections instead of null values. Okay, why not.
Therefore, well-educated Scala programmers use Option objects in Scala code. Okay, still better than NPE.
Therefore, well-educated Kotlin programmers may use kotlin.nullable and do some kind of the same magic. Although there is an “if” expression in Kotlin.
// yet, all Java libraries may return null values (ignorant Scala programmers could too, if they existed), so the problem is still not solved in Scala
Kotlin doesn’t have Option by design.
So, here is my first question: Why Kotlin programmers may want to threat nullable values as Collections at all? There is already a better, nearly perfect way to deal with it!
Now we have to go deeper. All calls to monadic functions for Collections like map, reduce or reverse are statically resolved during compilation. That’s the ideology.
Therefore, whenever Any?.reverse() is used, it definetely means that something is wrong with programmer’s expectations. This will be a great place to put a compilation warning, if not error.
Assuming that there is a great reason for this package, I have another question: Why all those transformations are done implicitly?
In my opinion, this goes against Kotlin’s deep philosophy: why am I forced write 5.toFloat(), but can write null.reverse() just on the next line?