Chaining scope functions helps you write clear and short code by running many actions on the same object in a row.
Chaining scope functions in Kotlin
val result = object.scopeFunction1 { // first block using 'this' or 'it' }.scopeFunction2 { // second block }.scopeFunction3 { // third block }
Scope functions like let, run, also, apply, and with can be chained.
Each function passes the object or the last result to the next, so you can do many things in one expression.
val text = "hello" val result = text .let { it.uppercase() } .also { println("Uppercase: $it") } .let { it.reversed() } println(result)
val number = 5 val result = number .run { this * 2 } .also { println("Doubled: $it") } .run { this + 3 } println(result)
val list = mutableListOf(1, 2, 3) list .apply { add(4) } .also { println("List after add: $it") } .apply { removeAt(0) } .also { println("List after remove: $it") }
val emptyString = "" val result = emptyString .let { if (it.isEmpty()) "Empty" else it } .also { println(it) }
This program creates a person, increases their age, prints the updated person, then changes the name to uppercase and prints the final result.
fun main() { val person = Person("Alice", 25) val updatedPerson = person .apply { age += 1 } // Increase age by 1 .also { println("After birthday: $it") } // Print person .run { copy(name = name.uppercase()) // Change name to uppercase } println("Final person: $updatedPerson") } data class Person(var name: String, var age: Int)
Time complexity depends on the operations inside each scope function, but chaining itself is very fast.
Space complexity is low since no extra large data structures are created during chaining.
A common mistake is confusing which scope function returns the original object and which returns a transformed result.
Use apply or also when you want to return the original object after changes.
Use let or run when you want to return a new value after transformations.
Chaining scope functions lets you do many things on one object in a clean, readable way.
Different scope functions return either the original object or a new result, so choose based on what you want to get back.
Use chaining to avoid repeating object names and keep your code short and clear.
Practice
Solution
Step 1: Understand the purpose of scope functions
Scope functions let you run code blocks on an object, often returning the object or a result.Step 2: Recognize chaining benefit
Chaining lets you call many scope functions one after another on the same object without repeating its name.Final Answer:
Perform multiple operations on one object without repeating its name -> Option AQuick Check:
Chaining scope functions = clean, repeated operations [OK]
- Thinking chaining creates new objects
- Confusing chaining with loops
- Believing chaining changes data types automatically
apply and also on an object obj?Solution
Step 1: Recall correct chaining syntax
In Kotlin, scope functions are called with dot notation and lambda blocks inside curly braces.Step 2: Check each option
obj.apply { }.also { } uses correct dot chaining with braces. obj.apply() also() misses dots and braces. apply(obj) { } also { } uses wrong function call style. obj.apply { } also { } misses dot beforealso.Final Answer:
obj.apply { }.also { } -> Option AQuick Check:
Dot + braces = correct chaining syntax [OK]
- Omitting dots between functions
- Using parentheses instead of braces for lambdas
- Calling scope functions like regular functions without object
val result = "hello".also { println(it.uppercase()) }.length
println(result)Solution
Step 1: Understand
alsobehavioralsoruns the lambda with the object asit, prints uppercase "HELLO", then returns the original string "hello".Step 2: Calculate
Afterresultalso,lengthis called on "hello", which is 5. Thenprintln(result)prints 5.Final Answer:
HELLO 5 -> Option DQuick Check:
also prints uppercase, length returns 5 [OK]
- Thinking also returns uppercase string
- Confusing print order
- Expecting length to be printed before uppercase
val text = "kotlin"
text.let { it.uppercase() }.apply { println(this) }Solution
Step 1: Analyze
letreturn valueletreturns the lambda result, hereit.uppercase(), a new String "KOTLIN".Step 2: Check
applyreceiverapplyis called on the uppercase string, sothisinsideapplyis "KOTLIN" andprintln(this)prints "KOTLIN".Step 3: Identify the problem
The originaltextis "kotlin", butapplyprints the uppercase string, not the original. This may be unexpected if you want to print original.Final Answer:
let does not return the original object, so apply prints wrong value -> Option CQuick Check:
let returns lambda result, not original object [OK]
- Assuming let returns original object
- Thinking apply needs braces
- Believing no error exists
val nums = mutableListOf(1, 2, 3), which chained scope function call correctly adds 4, prints the list, and returns the updated list?Solution
Step 1: Understand return values of scope functions
applyreturns the original object after running the block,alsoreturns the original object too,letreturns lambda result,runreturns lambda result.Step 2: Check each option
nums.apply { add(4) }.also { println(it) } adds 4 insideapply, then prints list inalso, returning the updated list. nums.let { it.add(4) }.also { println(it) }'sletreturnsUnitfromadd, soalsoprintsUnit. nums.also { add(4) }.apply { println(this) } has syntax error ('add' unresolved inalsoblock, needsit.add(4)). nums.run { add(4); println(this) } returnsUnitfromrun.Final Answer:
nums.apply { add(4) }.also { println(it) } -> Option BQuick Check:
apply returns object, also prints it [OK]
- Using let which returns Unit from add
- Expecting run to return the list
- Confusing order of operations in chaining
Ready to prove it?
Pass the test and this pattern moves unknown
