Bird
Raised Fist0
Kotlinprogramming~10 mins

Closures and variable capture in Kotlin - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Closures and variable capture
Define outer function
↓
Create inner function
↓
Inner function captures outer variable
↓
Return inner function
↓
Call inner function later
↓
Inner function uses captured variable
A closure is a function that remembers variables from its surrounding scope even after that scope has finished.
Execution Sample
Kotlin
fun makeCounter(): () -> Int {
    var count = 0
    return {
        count += 1
        count
    }
}

val counter = makeCounter()
println(counter())
println(counter())
This code creates a counter function that remembers and updates the count variable each time it is called.
Execution Table
StepActionVariable 'count'Returned ValueOutput
1Call makeCounter()count = 0 (initialized)Returns inner function
2Call counter() first timecount = 1 (incremented)1Prints 1
3Call counter() second timecount = 2 (incremented)2Prints 2
4No more callscount = 2 (final)Execution ends
💡 No more calls to counter(), so execution stops.
Variable Tracker
VariableStartAfter 1After 2Final
count0122
Key Moments - 2 Insights
Why does the inner function remember the variable 'count' even after makeCounter() finishes?
Because the inner function forms a closure that captures 'count' from its outer scope, keeping it alive as shown in execution_table steps 2 and 3.
What happens if we call makeCounter() again to create a new counter?
A new 'count' variable is created fresh for that new closure, independent from the first one, so counts do not mix.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of 'count' after the second call to counter()?
A2
B1
C0
D3
💡 Hint
Check the 'Variable count' column at Step 3 in the execution_table.
At which step does the inner function first increment 'count'?
AStep 1
BStep 3
CStep 2
DStep 4
💡 Hint
Look at the 'Action' and 'Variable count' columns in execution_table for when count changes from 0 to 1.
If we create a second counter by calling makeCounter() again, what will be the initial value of 'count' for it?
A1
B0
C2
DUndefined
💡 Hint
Recall that each call to makeCounter() initializes 'count' to 0 as in Step 1.
Concept Snapshot
Closures capture variables from their outer scope.
In Kotlin, inner functions can access and modify these variables.
Captured variables live as long as the closure.
Each closure has its own copy of captured variables.
Use closures to keep state between calls.
Full Transcript
This example shows how a Kotlin function makeCounter returns another function that remembers a variable 'count'. When makeCounter is called, it sets count to 0 and returns an inner function. This inner function increases count by 1 each time it is called and returns the new count. The variable 'count' is captured by the closure, so it stays alive even after makeCounter finishes. Calling counter() twice shows count increasing from 0 to 1, then 2. This demonstrates how closures keep variables alive and allow functions to remember state.

Practice

(1/5)
1. What does a closure in Kotlin do with variables from its surrounding scope?
easy
A. It copies the variables but cannot modify them.
B. It deletes those variables to save memory.
C. It ignores variables outside its own body.
D. It remembers and can use those variables even after the outer function ends.

Solution

  1. Step 1: Understand closure behavior

    A closure is a function that keeps access to variables from where it was created, even if that place no longer exists.
  2. Step 2: Apply to Kotlin closures

    In Kotlin, lambdas capture variables from the surrounding scope and can use them later.
  3. Final Answer:

    It remembers and can use those variables even after the outer function ends. -> Option D
  4. Quick Check:

    Closure remembers and can use variables even after outer ends = C [OK]
Hint: Closures keep variables alive beyond their original scope [OK]
Common Mistakes:
  • Thinking closures delete outside variables
  • Believing closures only copy variables without access
  • Assuming closures ignore outside variables
2. Which of the following is the correct syntax to create a lambda that captures a variable count in Kotlin?
easy
A. val lambda = (count) -> println(count)
B. val lambda = { println(count) }
C. val lambda = fun(count) { println(count) }
D. val lambda = { count -> println() }

Solution

  1. Step 1: Identify lambda syntax capturing external variable

    In Kotlin, a lambda can access variables from outside without parameters by just using them inside curly braces.
  2. Step 2: Check each option

    val lambda = { println(count) } correctly uses count from outside. val lambda = (count) -> println(count) tries to declare a parameter but syntax is wrong. val lambda = fun(count) { println(count) } uses fun keyword incorrectly. val lambda = { count -> println() } declares a parameter but does not use it properly.
  3. Final Answer:

    val lambda = { println(count) } -> Option B
  4. Quick Check:

    Lambda uses outside variable directly = A [OK]
Hint: Use curly braces and refer to outside variables directly [OK]
Common Mistakes:
  • Trying to declare external variables as lambda parameters
  • Using incorrect lambda syntax with fun keyword
  • Not referencing the variable inside the lambda body
3. What will be the output of the following Kotlin code?
fun main() {
    var x = 5
    val closure = { x += 1; println(x) }
    closure()
    closure()
    println(x)
}
medium
A. 6\n7\n7
B. 6\n6\n5
C. 6\n7\n5
D. 5\n5\n5

Solution

  1. Step 1: Trace the closure calls and variable changes

    Initially, x = 5. First closure call increments x to 6 and prints 6. Second call increments x to 7 and prints 7.
  2. Step 2: Print final value of x

    After two increments, x is 7, so printing x outputs 7.
  3. Final Answer:

    6\n7\n7 -> Option A
  4. Quick Check:

    Closure increments x twice, final x = 7 [OK]
Hint: Closures can modify captured vars; track changes stepwise [OK]
Common Mistakes:
  • Assuming closure uses a copy of x, not the original
  • Forgetting x increments on each closure call
  • Confusing printed values with initial x
4. Identify the error in this Kotlin code that tries to capture a variable inside a loop:
fun main() {
    val funcs = mutableListOf<() -> Unit>()
    for (i in 1..3) {
        funcs.add { println(i) }
    }
    funcs.forEach { it() }
}
medium
A. All lambdas print 3 instead of 1, 2, 3
B. Runtime error: variable i not found
C. Lambdas print 1, 2, 3 correctly
D. Syntax error: cannot capture loop variable

Solution

  1. Step 1: Understand variable capture in Kotlin loops

    Kotlin captures the loop variable i correctly for each lambda, so each lambda remembers its own i value.
  2. Step 2: Check output of lambdas

    When calling each lambda, they print 1, 2, and 3 respectively, no error occurs.
  3. Final Answer:

    Lambdas print 1, 2, 3 correctly -> Option C
  4. Quick Check:

    Kotlin captures loop vars per iteration = B [OK]
Hint: Kotlin captures loop vars freshly each iteration [OK]
Common Mistakes:
  • Assuming all lambdas print the last loop value
  • Expecting syntax or runtime errors for capturing loop vars
  • Confusing Kotlin behavior with other languages like JavaScript
5. You want to create a list of functions in Kotlin, each printing a different number from 1 to 3. Which code correctly captures the variable to avoid all functions printing the same number?
val funcs = mutableListOf<() -> Unit>()
for (i in 1..3) {
    // What to do here?
}
funcs.forEach { it() }
hard
A. for (i in 1..3) { funcs.add { println(i) } }
B. for (i in 1..3) { val x = i + 1; funcs.add { println(x) } }
C. for (i in 1..3) { funcs.add { println(i + 1) } }
D. for (i in 1..3) { val x = i; funcs.add { println(x + 1) } }

Solution

  1. Step 1: Understand variable capture in Kotlin for loops

    In Kotlin, lambdas added inside a for (i in 1..3) capture the i from their iteration correctly.
  2. Step 2: Check each snippet

    funcs.add { println(i) } prints 1 then 2 then 3. The snippet with val x = i + 1; funcs.add { println(x) } prints 2 3 4. funcs.add { println(i + 1) } prints 2 3 4. val x = i; funcs.add { println(x + 1) } prints 2 3 4.
  3. Final Answer:

    for (i in 1..3) { funcs.add { println(i) } } -> Option A
  4. Quick Check:

    Direct println(i) in for loop lambda = B [OK]
Hint: Directly use loop var i inside lambda [OK]
Common Mistakes:
  • Declaring x = i + 1 and printing x (prints 2 3 4)
  • Printing i + 1 directly (prints 2 3 4)
  • Copying to x = i but printing x + 1 (prints 2 3 4)
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard