I really want to write a function like this:
inline fun <T?> T?.ifExists (f :(T) -> Unit) :Unit { if (this != null) f(this) }
So that I can write code like this:
someMap[someKey].ifExists { value ->
// do stuff
}
I know that I can write:
someMap[someKey]?.let { value ->
// do stuff
}
but that’s making a confusing combination of the notion of a let binding with a null check in a way that is subtle and misleading IMO.
I could also write:
val value = someMap[someKey] ; if (value != null) {
// do stuff
}
but that is a lot more verbose than ifExists.
I also like the idea that if I were able to declare ifExists as I describe it above, it would not compile if I tried to use it on a non-nullable type. Which is good, because it doesn’t make sense to ask if something exists when it is guaranteed to exist. In such cases, I should be using let.
Anyhow, is there a way to do this that I’m missing, or is this a limitation of the “special” nature of nullable types? If T? was syntactic sugar for a real type (like Option<T>) then it would make sense to write:
inline fun <T, O :Option<T>> O.ifExists (f :(T) -> Unit) :Unit { if (this.isDefined()) f(this.get()) }
or something like that. However, I’m assuming that’s not how things work under the hood, so I’m wondering if there’s another way to express what I want, or if support for abstracting over nullable types with generics is in the cards some day?