Tricky output-based questions on Closures — Part I

Janvi Arora
2 min readMay 1, 2024

--

var closures: [() -> Void] = []

for i in 0..<3 {
closures.append {
print(i)
}
}

for closure in closures {
closure()
}

Output Explanation:

  • This code snippet creates an array of closures that each print the current value of i.
  • However, due to the closure-capturing behavior in Swift, all closures will capture and share the same i variable.
  • At the time the closures are executed, the value of i will be 3 because it's the value that completes the loop.
  • So, the output will be: 3 3 3.
func delayPrint() {
for i in 1...3 {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(i)) {
print(i)
}
}
}

delayPrint()

Output Explanation:

  • This code schedules three closures to print the value of i after a delay of 1, 2, and 3 seconds respectively.
  • However, the loop completes execution before the closures execute, and at that time, i will be 4.
  • So, when the closures execute, they will all print 4.
  • The output will not be in sequential order due to the asynchronous nature of DispatchQueue.main.asyncAfter.
  • Possible output could be: 4 4 4.
var numbers = [1, 2, 3, 4, 5]
var doubledNumbers = numbers.map { $0 * 2 }
numbers[0] = 10
print(doubledNumbers)

Output Explanation:

  • The map function creates a new array (doubledNumbers) by applying the closure to each element of the original array (numbers).
  • However, map creates a copy of the array elements, not a reference.
  • So, modifying numbers after creating doubledNumbers doesn't affect the elements in doubledNumbers.
  • Therefore, the output will be: [2, 4, 6, 8, 10].
var result: Int?

let closure1 = { result = 10 }
let closure2 = { [result] in print(result) }

closure1()
closure2()

Output Explanation:

  • closure1 captures and modifies the result variable.
  • closure2 captures result as a constant at the time of its creation.
  • When closure1 is called, it sets result to 10.
  • When closure2 is called, it prints the captured value of result, which is nil because it was captured before closure1 executed.
  • So, the output will be: nil.
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1
return count
}
}

let counter1 = makeCounter()
let counter2 = makeCounter()

print(counter1())
print(counter2())
print(counter1())
print(counter2())

Output Explanation:

  • The makeCounter function returns a closure that increments and returns a counter value.
  • Each call to makeCounter creates a new instance of the count variable.
  • counter1 and counter2 are two separate closures with their own instances of count.
  • So, the output will be: 1, 1, 2, 2.

--

--

No responses yet