0Pricing
Kotlin Academy · Lesson

apply and with: Configure and Return

Use apply and with to configure objects and understand their return values.

apply and with: Configure and Return is a free Kotlin Academy lesson on CoddyKit — lesson 1 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.

Scope Function Recap

Kotlin's scope functions (apply, also, let, run, with) let you execute a block in the context of an object. Each differs by receiver (this vs it) and return value.

apply Basics

apply { ... } runs the block with this bound to the receiver and returns the receiver itself. Perfect for object configuration.

class Person {
    var name: String = ""
    var age: Int = 0
}
fun main() {
    val p = Person().apply {
        name = "Ada"
        age = 35
    }
    println("${p.name}, ${p.age}")
}

Why apply Is Useful

Without apply, you'd need a temporary variable to configure and then return it. apply compresses this to a single expression.

class Config {
    var host: String = ""
    var port: Int = 0
}
fun makeConfig(): Config {
    // Without apply:
    // val c = Config(); c.host = "x"; c.port = 8080; return c
    return Config().apply {
        host = "localhost"
        port = 8080
    }
}
fun main() {
    val c = makeConfig()
    println("${c.host}:${c.port}")
}

apply in a Chain

apply returns the receiver, so it chains naturally into further method calls.

class Builder {
    val parts = mutableListOf<String>()
}
fun main() {
    val result = Builder().apply {
        parts.add("hello")
        parts.add("world")
    }.parts.joinToString(" ")
    println(result) // hello world
}

with Basics

with(receiver) { ... } runs the block with this = receiver and returns the lambda result (NOT the receiver). Useful when you want a derived value.

class Rect(val w: Int, val h: Int)
fun main() {
    val area = with(Rect(3, 4)) {
        w * h
    }
    println(area) // 12
}

apply vs with

apply returns the receiver, perfect for builders. with returns the lambda result, perfect for computing from a receiver.

class Box(var width: Int = 0, var height: Int = 0)
fun main() {
    val box = Box().apply { width = 10; height = 20 } // returns Box
    val area = with(box) { width * height }            // returns Int
    println("$box area=$area")
}

apply with Lists

Configure a mutable collection inline.

fun main() {
    val list = mutableListOf<String>().apply {
        add("a")
        add("b")
        add("c")
    }
    println(list)
}

apply Returns the Same Type

The return type of apply is always the receiver type. No need for an explicit return.

class Sb {
    private val buf = StringBuilder()
    fun append(s: String): Sb { buf.append(s); return this }
    fun build(): String = buf.toString()
}
fun main() {
    val s = Sb().apply {
        append("Hello, ")
        append("Kotlin!")
    }.build()
    println(s)
}

with Reusing Multiple Members

Inside with, all members of the receiver are in scope — no obj. prefix needed.

class Person(val name: String, val age: Int)
fun main() {
    val description = with(Person("Ada", 35)) {
        "Name: $name, Age: $age, AgeNext: ${age + 1}"
    }
    println(description)
}

Nested apply

You can nest apply inside another apply for hierarchical configuration. Use sparingly.

class Address {
    var city: String = ""
    var zip: String = ""
}
class User {
    var name: String = ""
    var address: Address = Address()
}
fun main() {
    val u = User().apply {
        name = "Ada"
        address.apply {
            city = "Istanbul"
            zip = "34000"
        }
    }
    println("${u.name} in ${u.address.city}")
}

When NOT to Use apply

If you don't need to return the receiver, prefer plain construction with named arguments or let/run. Don't use apply just for variety.

class Config(val host: String, val port: Int)
fun main() {
    // Named arguments often beat builder + apply:
    val cfg = Config(host = "localhost", port = 8080)
    println("${cfg.host}:${cfg.port}")
}

Quick Check

What does apply return after running its block?

Recap

apply runs a block with this = receiver and returns the receiver — perfect for object configuration. with runs a block with this = receiver and returns the lambda result — perfect for derived values. Use named arguments when configuration is simple.

Frequently asked questions

Is the “apply and with: Configure and Return” lesson free?

Yes — the full text of “apply and with: Configure and Return” 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 “apply and with: Configure and Return”?

Use apply and with to configure objects and understand their return values. 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 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “apply and with: Configure and Return” 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