Skip to content

Instantly share code, notes, and snippets.

@dcastro
Last active September 4, 2017 18:41
Show Gist options
  • Save dcastro/69cecd670ccd78ab0ff33626f33db3b2 to your computer and use it in GitHub Desktop.
Save dcastro/69cecd670ccd78ab0ff33626f33db3b2 to your computer and use it in GitHub Desktop.
Nested nullables in Kotlin
// A function that takes an instance of `T` and returns a nullable `T?`
fun <T>toNullable(t: T): T? {
return t
}
// If we pass in a `String`, we get back a `String?`
val s1 : String? = toNullable("" as String)
// So, if we pass in a `String?`, we get back a nested nullable `String??`, right?
// Wrong. We get a `String?`
val s2 : String? = toNullable("" as String?)
// It looks like Kotlin can't express nested nullables
// Why is this important?
// Let's have a look at `Map<K, V>`
// It defines the following method: get(key: K): V?
// Notice how it returns `V?`, where `null` is used to signal that there's no entry for a given `key`
val map = hashMapOf<String, Int>("key1" to 1)
val val1: Int? = map.get("key1")
val val2: Int? = map.get("key2")
println(val1 == null) // false
println(val2 == null) // true
// However, when we have a map with a nullable value, like `Map<String, Int?>`, the meaning of `null` is now ambiguous
// It can both mean that the entry doesn't exist, or that it exists but has no value
val map = hashMapOf<String, Int?>("key1" to 1, "key2" to null)
val val1: Int? = map.get("key1")
val val2: Int? = map.get("key2")
val val3: Int? = map.get("key3")
println(val1 == null) // false
println(val2 == null) // true
println(val3 == null) // true
// Contrast this with what happens in Swift, where we can have a nested `Int??`
let map: [String: Int?] = ["key1": 1, "key2": nil]
let val1: Int?? = map["key1"]
let val2: Int?? = map["key2"]
let val3: Int?? = map["key3"]
print(val1 == nil) // false - entry exists
print(val1! == nil) // false - value exists
print(val2 == nil) // false - entry exists
print(val2! == nil) // true - value doesn't exist
print(val3 == nil) // true - entry doesn't exist
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment