skip to content

What does Kotlin's let scope function do, and how do you access the value inside its lambda?

level: juniorimportance: must knowfreq 80%

answer

  1. Receiver in as it, lambda result out
  2. inline extension fun T.let(block: (T) -> R): R
  3. Does NOT return the original object
  4. it is the implicit single-param name
  5. Transform / scope a temporary name

basics

~10 s

let runs a block of code on a value. Inside the block the value is called it, and let returns whatever the last line of the block produces.

solid answer

~30 s

let is an extension function callable on any value. It takes a lambda and passes the receiver object into that lambda as the implicit parameter it. The return value of let is the result of the lambda (its last expression), NOT the original object. So `val len = name.let { it.length }` gives the length. This makes let useful for transforming a value into something else and for scoping a temporary name to a small block. You can rename it: `name.let { n -> n.length }`. Contrast with also/apply, which pass the object as receiver and return the object itself.

code

kotlin · 5 lines
kotlin
val name = "Kotlin"
val length = name.let { it.length }        // 6  (lambda result returned)
val shout  = name.let { s -> s.uppercase() } // "KOTLIN" (renamed param)
println(length)
println(shout)

go deeper

for a junior

Knows let passes the value as it and returns the lambda result.

for a middle

Distinguishes let (it / lambda result) from apply/also (this or it / receiver) and uses it to transform values.

for a senior

Mentions the inline signature, no allocation, and chooses let deliberately for value transformation and scoping.

for a principal

Frames let within the full scope-function decision matrix and sets team conventions on when renaming it improves readability.

## What `let` is `let` is one of Kotlin's five **scope functions** (the others are `run`, `with`, `apply`, `also`). It is defined in the standard library as an **inline extension function** on a generic receiver: ```kotlin public inline fun <T, R> T.let(block: (T) -> R): R = block(this) ``` Because it is `inline`, the lambda body is inlined at the call site — there is no runtime lambda object allocation. ## The two defining behaviours 1. **The receiver is passed as the lambda argument `it`.** Inside the block you refer to the object as `it` (the implicit single-parameter name), not as `this`. You may rename it: `value.let { v -> ... }`. 2. **`let` returns the lambda result.** Whatever the last expression of the block evaluates to becomes the value of the whole `let` call. It does NOT return the original receiver. ```kotlin val name = "Kotlin" val length: Int = name.let { it.length } // returns 6 val upper: String = name.let { it.uppercase() } // returns "KOTLIN" ``` ## Typical uses - **Transform a value** into a different type or shape and capture the result. - **Introduce a local name** for an expression so you don't repeat or recompute it: ```kotlin val result = computeExpensive().let { x -> x * x + x } ``` - **Run a block only on a non-null value** via `?.let { }` (covered separately). ## `it` vs renaming `it` is implicit only when the lambda has exactly one parameter. For readability inside longer blocks, give it a name: `user.let { u -> ... }`. ## Contrast (so you pick the right tool) - `let` / `run`: return the **lambda result**. - `apply` / `also`: return the **receiver object** (used for configuration/side effects). - `let` / `also`: expose the object as **`it`**; `run` / `with` / `apply`: as **`this`**.

  • Does let return the original object or the lambda result?
    The lambda result — the value of the last expression in the block. Use also if you want the original object back.
  • Can you rename it inside let?
    Yes: name.let { n -> n.length }. it is just the default name when the lambda has one parameter.

let is like a vending machine: you put the object in (as it) and get back whatever the block dispenses, not your original coin.

saying these in an interview costs you the question

  • Saying let returns the original receiver (that's apply/also)
  • Referring to the value as this inside let (it's it)
  • Claiming let can take multiple parameters
  • Confusing let with with (with takes the object as an argument, not as a receiver call)

context