Sitemap

Kotlin Scope Functions

2 min readOct 7, 2026

--

write cleaner and more idiomatic code

Press enter or click to view image in full size

✨ Introduction

Kotlin’s scope functions (let, run, with, apply, also) are powerful tools for writing concise, readable code. They allow you to perform operations on objects within a temporary scope, reducing boilerplate and improving clarity. Let’s break down each function with practical examples.

1. let: Transform and Null-Check

Use let for null-safe transformations or actions on nullable objects:

val name: String? = "Kotlin"
name?.let {
println(it.uppercase()) // "KOTLIN"
it.length // Returns length (last expression)
}

🤔 When to use:

  • Null-checking nullable variables.
  • Transforming an object and returning a result.

2. run: Configure or Compute

run works on an object (receiver) and returns the last expression:

val result = "Hello".run {
println("Length: $length") // Length: 5
substring(0, 3) // Returns "Hel"
}

Non-extension variant:

run {
val x = 5
x * x // Returns 25
}

🤔 When to use:

  • Initializing objects + computing a value.
  • Grouping logic on an object.

3. with: Group Operations

with is similar to run but takes the receiver as an argument:

val list = mutableListOf(1, 2, 3)
val firstEven = with(list) {
add(4)
firstOrNull { it % 2 == 0 } // Returns 2
}

🤔 When to use:

  • Performing multiple operations on the same object.
  • Avoiding repeated list. or object. prefixes.

4. apply: Initialize Objects

apply returns the receiver after configuration:

val task = Task().apply {
id = 101
priority = HIGH
assignee = "Alice"
}
// Returns configured Task object

🤔 When to use:

  • Configuring properties during object creation.
  • Builder-style initialization.

5. also: Side Effects

also returns the receiver after performing side effects:

val numbers = listOf(1, 2, 3)
.also { println("Original: $it") } // Logging
.map { it * 2 }

🤔 When to use:

  • Debugging/logging.
  • Performing actions without altering the object.

Key Differences Cheat Sheet

Press enter or click to view image in full size

Best Practices

  1. Avoid nesting scope functions (e.g., apply inside let).
  2. Use it for let/also and this for run/apply/with to clarify context.
  3. Prefer takeIf/takeUnless with let for conditional checks:
user.takeIf { it.isActive }?.let { sendEmail(it) }

Conclusion

Kotlin’s scope functions eliminate redundancy and make code expressive. Remember:

  • Use let for null-safe ops.
  • Use run/with for computations.
  • Use apply for initializers.
  • Use also for side effects.

Master these to write idiomatic Kotlin!

Get Tejas Kanazriya’s stories in your inbox

Join Medium for free to get updates from this writer.

References:

Let me know if you’d like a deep-dive into any specific scope function! 🚀

--

--

Tejas Kanazriya
Tejas Kanazriya

Written by Tejas Kanazriya

Jr. Mobile App Developer | Kotlin | Flutter | Jetpack