Home > Software design >  How create extension function ifNullOrEmpty?
How create extension function ifNullOrEmpty?

Time:06-28

I want to create a function like ifEmpty() of Kotlin that will also check for null:

ifNullOrEmpty{
  //some code if null or empty
}

How can i do this?

And does anyone know what the code below is called?

: R where C : CharSequence, C : R

Example of Kotlin ifEmpty() function.

@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
public inline fun <C, R> C.ifEmpty(defaultValue: () -> R): R where C : CharSequence, C : R =
    if (isEmpty()) defaultValue() else this

Thanks and have a nice day!

CodePudding user response:

does anyone know what the code below is called?

You are mixing 2 pieces in your snippet:

  • : R is simply the return type of the function
  • where C : CharSequence, C : R is called a where clause. Its purpose is to specify multiple upper bounds on the type parameters of the function.

How can i do this?

Regarding the implementation itself, you may not be able to use as many generics as the original ifEmpty (due to @InlineOnly being internal), but you can do a simpler version if this is enough for you:

inline fun <R : CharSequence> R?.ifNullOrEmpty(defaultValue: () -> R): R =
    if (isNullOrEmpty()) defaultValue() else this

The difference with the stdlib's ifEmpty is that the lambda in this case cannot widen the type (you can't return a CharSequence from the lambda if you called ifNullOrEmpty on a String), but this should rarely be needed.

CodePudding user response:

As explained in other answers, you can't create ifNullOrEmpty() with similar generic logic as in ifNull(), because you need @InlineOnly which is currently internal and can be used by stdlib only.

If you don't mind using internal components and writing code that is potentially not forward-compatible, you can utilize a small hack:

@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@kotlin.internal.InlineOnly
public inline fun <C, R> C.ifNullOrEmpty(defaultValue: () -> R): R where C : CharSequence, C : R =
    if (isNullOrEmpty()) defaultValue() else this

Alternatively, you can use "less generic" implementation as provided by @Joffrey, which should be sufficient for most use cases.

CodePudding user response:

Honestly I don't fully understand why the generic types are necessary in the original ifEmpty but I think you can just do it like this:

inline fun CharSequence?.ifNullOrEmpty(defaultValue: () -> CharSequence): CharSequence =
    if (isNullOrEmpty()) defaultValue() else this
  • Related