0Pricing
Kotlin Academy · Lesson

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 — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

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.

Frequently asked questions

Is the “Choosing the Right Scope Function: Decision Guide” lesson free?

Yes — the full text of “Choosing the Right Scope Function: Decision Guide” is free to read here on the web, and the Kotlin Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Kotlin Academy course, upgrade to CoddyKit PRO.

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; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

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

  1. apply and with: Configure and Return
  2. let and run: Transform and Scope
  3. also: Side Effects Without Changing the Receiver
  4. Choosing the Right Scope Function: Decision Guide
← Back to Kotlin Academy