4

In Kotlin, it's common to use let to execute code if an object (let receiver) isn't null, as an alternative to an if != null check, as in the following:

val nullable: String? = "anything"
nullable?.let {
    println(it)
}

In what other situations does it make sense to make use of let?

FYI, let is part of Kotlin's stdlib and is defined as follows:

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
  • 1
    There is an open style guide issue for this at https://github.com/yole/kotlin-style-guide/issues/35. – mkobit Nov 06 '17 at 19:12
  • 1
    Possible duplicate of [Example of when should we use run, let, apply, also and with on Kotlin](https://stackoverflow.com/questions/45977011/example-of-when-should-we-use-run-let-apply-also-and-with-on-kotlin) – Jacky Choi Nov 07 '17 at 05:49
  • The referred question doesn't really give alternative ways to use it, which is what I was asking for – s1m0nw1 Nov 08 '17 at 07:40

4 Answers4

5

I've seen let used to scope nested variables (ignoring let's return):

    some.nested.foo.bar.let { bar -> 
        doSomething(bar)
        doMoreStuff(bar)
    }

It can be nice since it replaces the need to define a local variable, but I'm not sure how useful it actually is.

Could also be done with apply, though the readability is a bit worse, (this instead of bar in the scope).

triad
  • 20,407
  • 13
  • 45
  • 50
2

let is also useful when you work with var variables which are nullable. For instance, we have this code

fun doSomething(value: String) {

}

class A {
    var boo: String? = null
    fun b() {
        if (boo != null) {
            doSomething(boo)
        }
    }
}

There, we have compile-time error inside if block because boo can be changed outside. To fix that we should either create a val variable

class A {
    var boo: String? = null
    fun b() {
        val b = boo
        if (b != null) {
            doSomething(b)
        }
    }
}

or use let

class A {
    var boo: String? = null
    fun b() {
        boo?.let {
            doSomething(it)
        }
    }
} 
vmtrue
  • 1,724
  • 18
  • 36
  • This does not make sense to me; why not just do ``boo?.length`` then? `let` is redundant – s1m0nw1 Nov 08 '17 at 07:48
  • 1
    @s1m0nw1 In this case, you are right. But I tried to show a case when you need not null variable. – vmtrue Nov 08 '17 at 08:06
  • 1
    @s1m0nw1 I've changed example – vmtrue Nov 08 '17 at 08:10
  • So know we're back to what I already suggested in the question itself, right? That's independent of `var`. – s1m0nw1 Nov 08 '17 at 08:26
  • 1
    @s1m0nw1 yes, you are right. It doesn't matter use either `if` or `let` with `val` but if you use `var` and `if` you have to declare a `val` variable – vmtrue Nov 08 '17 at 10:41
0

scoping capabilities

The stdlib function let enables you to confine a variable's scope to a specific block of code. Shown here:

compile("a:b:c")
"io.vertx:vertx".let { v->
    compile("$v-lang-kotlin:$vertxVersion")
    compile("$v-lang-kotlin-coroutines:$vertxVersion")
} 
compile("x:y:z")

We could alternatively define a val v: String = "io.vertx:vertx" which might make the code more readable since that's what we'd do in Java for example. Yet, that val would be accessible throughout the whole method. We just want to have it available for the compile units with vertx involved, thus we confine the variable holding io.vertx:vertx to the let block.

Informations on the different scoping function alternatives can be found in this thread.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
0

you can use let in let in let by naming

someMethodCall()?.let{ nameOne ->
       // ....
       // some code here
       // ....
       val resultCall = nameOne
       someMethod2Call()?.let { -> nameTwo
          // ...
          val myVariable = nameTwo + resultCall
          // ... 
      }
}
Rasoul Miri
  • 11,234
  • 1
  • 68
  • 78