Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin : How to use if-else like condition with let block for 'null' checks

I am replacing all the null checks with let block in my code as part of a code review process.

1. Code example with null check:

if(someValue != null){//run if someValue is not null}
else {//run if someValue is null}

2. Code base after using let-run block if for null check,

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?.run {
//This code block should run only when if someValue is null, like else condition
}

Now problem with let-run block is that both the code blocks are running even if the someValue is not null. So i am not able to replicate behaviour of if-else condition in code example 1 to run-let condition in code example 2.

Expected behaviour is to execute either let or run code block based upon if value is null or not-null.

like image 981
Arpit Avatar asked Jul 10 '19 16:07

Arpit


2 Answers

Source - kotlinlang.org

  • ?. performs a safe call (calls a method or accesses a property if the receiver is non-null)
  • ?: takes the right-hand value if the left-hand value is null (the elvis operator)

Change ?. with ?: will solve this issue,

Code base as following, will run either let or run block based upon the null check.

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?:run {
//This code block will run only when if someValue is null, like else condition
}
like image 80
Arpit Avatar answered Sep 18 '22 19:09

Arpit


I am replacing all the null check with let block in my code

The first question here is, why? Is this somehow more readable for you than the regular if-else structure? I'd be generally wary of refactoring just for refactoring's sake.

The second consideration is much more important: this conversion you're doing is not equivalent to the original code, you're actually modifying the behavior with this change. Take the following piece of code:

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
    foo(someSafeValue)
    bar(someSafeValue)
} ?: run {
    println("shouldn't happen if someValue != null")
}

You expect the run block to execute only if someValue == null, but that's actually not the only case when it will run. The entire someValue?.let { ... } expression can produce null values not just when someValue itself was null, but also if the block passed to let returned null. In this case, if the bar() function call results in null, the run statement will be executed afterwards, therefore running both branches of what you thought was a fancied up if-else statement.

like image 32
zsmb13 Avatar answered Sep 17 '22 19:09

zsmb13