Choosing the Right Scope Function: Decision Guide
Select the correct scope function based on receiver, return type, and intent.
Choosing the Right Scope Function: Decision Guide is a free Kotlin Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, and your progress syncs across the web and the CoddyKit app. The Kotlin Academy course includes 4 lessons in total.
Five Functions, Two Axes
Kotlin's scope functions vary on two axes: receiver style (this or it) and return value (receiver or lambda result). Pick based on intent.
The Decision Matrix
apply: this / receiver. also: it / receiver. run: this / lambda. let: it / lambda. with: this / lambda (no receiver via dot).
apply: Configure and Return
Use apply for object configuration in a builder-style chain.
class Config {
var host: String = ""
var port: Int = 0
}
fun main() {
val cfg = Config().apply {
host = "localhost"
port = 8080
}
println("${cfg.host}:${cfg.port}")
}also: Side Effects
Use also to log, validate, or trigger a side effect while passing the receiver through.
fun main() {
val items = listOf(1, 2, 3, 4)
.also { println("got ${it.size} items") }
.filter { it % 2 == 0 }
println(items)
}let: Transform and Scope Null Safety
Use let for null-safe transformations or to limit a variable's scope.
fun main() {
val name: String? = "Ada"
val length = name?.let { it.length } ?: 0
println(length)
}run: Multi-Member Access with Result
Use run when computing a result from many members of the receiver — saves it. prefixes.
class User(val name: String, val age: Int)
fun main() {
val description = User("Ada", 35).run {
"Name: $name, Age: $age"
}
println(description)
}with: Group Operations on an Existing Object
Use with(obj) { ... } when you don't own the call site (no dot-chain) but want to group operations using this.
class Builder {
val parts = mutableListOf<String>()
fun add(s: String) { parts.add(s) }
fun build(): String = parts.joinToString("-")
}
fun main() {
val b = Builder()
val result = with(b) {
add("hello")
add("kotlin")
build()
}
println(result) // hello-kotlin
}Choosing Based on Intent
Ask: (1) Do I need the receiver back or a derived result? (2) Do I prefer this or it? The answers pick the function.
class Box { var w = 0; var h = 0; fun area() = w * h }
fun main() {
// Configure and return Box -> apply
val box = Box().apply { w = 3; h = 4 }
// Compute area from box -> let or run
val area = box.let { it.area() }
// Side effect, keep box -> also
val sameBox = box.also { println("area=${it.area()}") }
println("$box / $area / $sameBox")
}Comparison: apply vs also
Both return the receiver. apply uses this (good for setting fields). also uses it (good for referencing the receiver explicitly, often in side effects).
class Item { var name = "" }
fun main() {
val a = Item().apply { name = "apply" } // implicit this
val b = Item().also { it.name = "also" } // explicit it
println("${a.name} / ${b.name}")
}Comparison: let vs run
Both return the lambda result. let uses it (good for simple transformations and null safety). run uses this (good when you call many members).
class Calculator(val a: Int, val b: Int) {
fun sum() = a + b
fun product() = a * b
}
fun main() {
val calc = Calculator(3, 4)
val s = calc.let { it.sum() } // simple
val combo = calc.run { "sum=${sum()} product=${product()}" } // multi-member
println("$s / $combo")
}Practical Pipeline
A real-world chain often uses multiple scope functions together.
class Request(var url: String = "", var headers: Map<String, String> = emptyMap())
fun main() {
val response = Request()
.apply {
url = "https://api.example.com"
headers = mapOf("Accept" to "json")
}
.also { println("request: ${it.url}") }
.let { req -> "GET ${req.url}" }
println(response)
}Cheat Sheet
Quick reference for picking the right tool.
// apply: this, returns receiver — configure object
// also: it, returns receiver — side effects in chain
// let: it, returns lambda result — transform / null-safety
// run: this, returns lambda result — multi-member compute
// with: this, returns lambda result — group operations on existing obj
fun main() { println("Scope functions: pick by receiver style + return value") }Quick Check
Which scope function takes this as the receiver AND returns the receiver itself?
Recap
Pick the scope function by intent: apply (config + return self), also (side effect + return self), let (transform with it), run (transform with this), with (group operations on an existing object). Two axes — receiver style and return value — determine the right choice.
Learn Kotlin with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “Choosing the Right Scope Function: Decision Guide” lesson free?
Yes — any 3 lessons of the Kotlin Academy learning path, including “Choosing the Right Scope Function: Decision Guide”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Kotlin Academy course includes 4 lessons in total.
What will I learn in “Choosing the Right Scope Function: Decision Guide”?
Select the correct scope function based on receiver, return type, and intent. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Academy?
No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
How long does the “Choosing the Right Scope Function: Decision Guide” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Academy lesson?
Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- apply and with: Configure and Return
- let and run: Transform and Scope
- also: Side Effects Without Changing the Receiver
- Choosing the Right Scope Function: Decision Guide