DEV Community

Cover image for “if vs let” in Kotlin
Khush Panchal
Khush Panchal

Posted on • Updated on • Originally published at Medium

“if vs let” in Kotlin

Let’s start with the problem:


class IfOrLet {

    private var string1: String? = "some string 1"

    init {
        if(string1 != null) {
            makeString1Null()
            println(string1) // prints null
        }
    }

    private fun makeString1Null() {
        string1 = null
    }

}
Enter fullscreen mode Exit fullscreen mode

Using If

In the above simple example, when we use “if”, we’re essentially checking a condition. For example, we might want to perform an action only if a certain variable is not null. This is useful for simple conditional checks. But?

Problem? What if during the execution of code inside “if”, some other thread makes “string1” null?

If we do any operation on “string1” considering it non null, our code may behave in wrong manner.

Solution? → Using “let

class IfOrLet {

    private var string1: String? = "some string 1"

    init {
        string1?.let { it ->
            makeString1Null() // <----- even if this make string1 null, the actual value before entering the let block (it) will not change
            println(it) // prints "some string 1"
        }
    }

    private fun makeString1Null() {
        string1 = null
    }

}
Enter fullscreen mode Exit fullscreen mode

Using let

In the above code, we can see even if the “string1" becomes null it will not affect the code inside “let” block. But how?

Let’s first check the code of “let” function

public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
Enter fullscreen mode Exit fullscreen mode

let” is an inline extension function in Kotlin which is better for dealing with nullable types. When we use “let” we’re saying, “if this variable is not null, do something with it.” In the above code, we used “string1?.let { … }”, where “{ … }” is the action you want to perform with “string1” if it’s not null.

Decompiled

Let’s check the decompiled version of above code to understand how “let” is thread safe:

public final class IfOrLet {
   private String string1 = "some string 1";

   private final void makeString1Null() {
      this.string1 = null;
   }

   public IfOrLet() {
// Decompiled form of "let"
      String var10000 = this.string1;
      String var1;
      if (var10000 != null) {
         var1 = var10000;
         this.makeString1Null();
         System.out.println(var1);
      }

// Decompiled form of "if"
      if (this.string1 != null) {
         this.makeString1Null();
         var1 = this.string1;
         System.out.println(var1);
      }

   }
}
Enter fullscreen mode Exit fullscreen mode

Ignoring the names, the main thing to notice above is that when we use “let”, it copies the original value (var10000) and use it for further calculation and doesn’t care about the actual value (string1).

One key difference between “if” and “let” is how they handle the variable they’re operating on. In above example, even if string1 becomes null inside the “let” block, the original value of string1 before entering the block is already copied. This makes “let” safer to use in situations where the value of the variable might change unexpectedly, such as in multithreaded environments.

Other Use Cases

One common use case for “let” is chaining operations on nullable variables. For example, you might have a nullable variable representing a user input, and you want to perform several operations on it only if it’s not null. You can chain multiple “let” calls together to handle this gracefully.

userInput?.let { validateInput(it) }?.let { processInput(it) }?.let { displayResult(it) }
Enter fullscreen mode Exit fullscreen mode

In this example, each “let” block only executes if the previous one returns a non-null result, allowing for safe and concise handling of nullable values.

Source code: Github

Contact Me:

LinkedIn, Twitter

Happy Coding ✌️

Top comments (1)

Collapse
 
nigel447 profile image
nigel447

++1 let is threadsafe