Abstracting over nullability


#1

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. :slight_smile:

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?


#2

You need to give a non nullable bound to T so that the ifExists parameter is non-null :
 
inline fun <T : Any> T?.ifExists (f: (T) -> Unit) :Unit { if (this != null) f(this) }

#3

Oh great, thanks!