3
\$\begingroup\$

Kotlin defines extension functions like also but they are not null checked. That's fine because you might not need the check. In case you do though, do you see any issue with the solution below?

inline fun <T> T?.ifNotNull(block: (T) -> Unit): T? {
    return this?.also {
        block(it)
    }
}

inline fun <T> T?.otherwise(block: () -> Unit) {
    this?: run {
        block()
    }
}

fun main(args: Array<String>) {
    "it".ifNotNull {
        println("You can use $it")
    }.otherwise {
        // will not happen
    }

    null.ifNotNull {
        // will not happen
    }.otherwise {
        println("You don't see it")
    }

}
\$\endgroup\$
1
\$\begingroup\$

OK, I'll give my answer. One problem I had trying this approach is that there are too many combinations: there are cases when you want to use also cases when you want to use let etc. It looks like having the operators and the extension functions independently defined gives you the advantage of a kind of strategy pattern when you can combine different strategies to have an exponential number of configuration without having to define an exponential number of functions.

So you have

Operators:

 1. `?.`
 2. `?:`

Extension functions

a) `also`
b) `let`
c) `run`
d) etc

then you can combine operator 1. with extension fun b) or operator 2. with extension fun c) etc

If you try to define extension funs with null checks then you need to define one function for each combination: it's even difficult just to find names for the functions

So I will keep the otherwise helper fun but I will not use if ifNotNull

\$\endgroup\$
1
\$\begingroup\$

I like @kingston's answer a lot, which is that basically that the functions you wrote are not necessary.

There is this stackoverflow question: How to run code if object is null? . The answer is to just use a plain if-else in such cases. See furthermore this linked answer from another question. It's just easier to read a plain if-else than other Kotlin solutions, such as this solution using the elvis operator. Another advantage is that you can use an if-else either to just run a code block that does something and returns nothing like your functions do, or you can instead use if-else as an expression and return some value.

I also think your functions are not very "functional" because they carry their action strictly by side effects. As mentioned above, the block does something and returns nothing. In a more functional style, functions are chained and return transformed values at each stage.

The signature of ifNotNull is a bit odd since it runs a block that returns nothing and ifNotNull returns the raw object on which it is called instead. I know this is so you can chain ifNotNull and otherwise, but the signature looks odd nonetheless.


Some extra code related to the comment below showing the compiler automatically knows a variable (val or var) within an if (x != null) { } block is not null:

fun main(args: Array<String>) {
    var s: String? = "asfd"
    // println(s.length)  // Compile error.  Need s!!.length

    if (s == null) {
        println("null")
    } else {
        println("${s::class::simpleName}")
        println(s.length)  // compiles without or with s!!.length
    }
}
\$\endgroup\$
  • \$\begingroup\$ Thank you. The problem with if-else is that if the variable is a var and not a val you either need to convert it into a val or you need to use the operator '!!' that's risky. \$\endgroup\$ – kingston May 16 '18 at 7:02
  • \$\begingroup\$ I don't know Kotlin much and I'm not sure what you are referring to. I guest you are talking about the compiler automatically knowing that a var is not null within a if (x != null) { } block. I tried with both var and val and it works fine in both cases without needing !!. I edited my answer to add sample code. \$\endgroup\$ – toto2 May 16 '18 at 13:56
  • \$\begingroup\$ @kingston I just realized you both asked the question and answered it. See my reply above. \$\endgroup\$ – toto2 May 16 '18 at 14:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.