Kotlin: run, let, apply, also, with — when to use what? Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Kotlin: run, let, apply, also, with — when to use what? Full breakdown with examples



Hello, friend! If you're learning Kotlin and want to write clean, concise code, you'll sooner or later encounter five magical functions: run, let, apply, also, and with. These are scope functions — they allow you to execute code in the context of an object and greatly simplify your life.



But here's the catch: many beginners (and not only) get confused about when to use which. This question is one of the most popular on Stack Overflow, and today we'll finally figure out how not to make a mistake. We won't just list the rules — we'll show real-world examples from practice that you can immediately use in your projects.



What are scope functions and why are they needed?

Scope functions are functions that create a temporary scope for an object. Inside this scope, you can refer to the object via it or this. The main difference between them is how they return the result and how they refer to the context.



Here's a quick cheat sheet that we'll fill with examples:

  • let — context: it, returns: lambda result. Used for null checks and call chains.
  • run — context: this, returns: lambda result. A universal function, often used for initialization and computations.
  • apply — context: this, returns: the object itself. Ideal for configuring object properties.
  • also — context: it, returns: the object itself. Good for additional actions (logging, checks).
  • with — not an extension function, context: this, returns: lambda result. Convenient for grouping calls on one object without creating a new one.


Remember the main rule: the choice of function depends on what you need — to return the object or the result, and how you want to refer to the context (via it or this).



1. let — the king of safe chains

let is your best friend when you need to work with nullable objects. It executes the code only if the object is not null. The context is passed as it.



Example: safe transformation

val name: String? = "Andrey"// Without let:if (name != null) {    println("Name length: ${name.length}")}

// With let (much more elegant):name?.let { println("Name length: ${it.length}")}


let is also great for operation chains. For example, when you need to transform one object into another:



val numbers = listOf(1, 2, null, 4, null, 6)val nonNullSquared = numbers    .mapNotNull { it }    .let { list ->        list.map { it * it }    }println(nonNullSquared) // [1, 4, 16, 36]


When to use let:

  • Null checks (the most common case).
  • Transforming one value into another.
  • Executing a chain of operations on a result.


2. apply — the constructor without extra words

apply returns the object itself, and inside the lambda the context is this. This is the ideal tool for configuring an object before use. Forget about long set blocks!



Example: configuring a View (Android) or data class

data class User(var name: String = "", var age: Int = 0)

val user = User().apply { name = "Maria" age = 25}println(user) // User(name=Maria, age=25)

// Even cooler — configuring a TextView:val textView = TextView(context).apply { text = "Hello, Kotlin!" textSize = 18f setTextCo

Blogs

Book Recommendations