Scope Functions: let, run, apply, also, with
What are scope functions?
Scope functions let you run a block of code on an object without repeating its name. They look similar at first, so the goal of this lesson is to know exactly when to use each one. The difference is two things: how you refer to the object (it or this) and what the block returns (the object or the last line).
| Function | Object is | Returns | Use for |
|---|---|---|---|
let | it | last line | null checks, transforms |
run | this | last line | compute a result |
apply | this | the object | configure an object |
also | it | the object | side effects (logging) |
with | this | last line | group calls on one object |
let — null checks and transforms
val name: String? = getName()
name?.let {
println("Hello, $it") // runs only if name is not null
}
val length = name?.let { it.trim().length } ?: 0
apply — configure and return the object
val paint = Paint().apply {
color = Color.RED // 'this' is the Paint
strokeWidth = 4f
isAntiAlias = true
} // returns the configured Paint
also — do a side effect, keep the object
val numbers = mutableListOf(1, 2, 3)
.also { println("Before: $it") }
.apply { add(4) }
.also { println("After: $it") }
run and with — group operations
val area = run {
val w = 4; val h = 5
w * h // returns 20
}
with(user) {
println(name) // 'this' is user
println(email)
}
A practical comparison
// configure (apply) vs transform (let)
val textView = TextView(context).apply {
text = "Hello"
textSize = 18f
}
val upper = "hello".let { it.uppercase() } // "HELLO"
Common mistakes
- Nesting many scope functions until
it/thisbecome confusing — keep it shallow. - Using
applywhen you actually want the computed result (userun/let). - Overusing them for trivial code where a plain variable is clearer.
Summary:apply/alsoreturn the object (configure / side effects);let/run/withreturn the last line (transform / compute). Pick by what you need back and whether you preferitorthis.