Kindred
Kindred

Reputation: 1269

Does values capturing of closure in swift means creating static variable?

In Capturing Values section of swift documentation:

... It does this by capturing a reference to runningTotal and amount from the surrounding function and using them within its own function body. ...

and

If you create a second incrementer, it will have its own stored reference to a new, separate runningTotal variable.

So I try the following testing and get a conclusion that since each incrementer made by the makeIncrementer(forIncrementer:) has its own runningTotal and the value of runningTotal is remembered by each incrementer, what values-capturing does is equivalent to creating some static variable(s) for a closure. But I'm not sure whether my statement is correct.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }

    return incrementer
}

let by10Incrementer = makeIncrementer(forIncrement: 10)
let by20Incrementer = makeIncrementer(forIncrement: 20)

for i in 0..<5 {
    print(by10Incrementer())
}

print("---")

for j in 0..<5 {
    print(by20Incrementer())
}

output:

10
20
30
40
50
---
20
40
60
80
100

I originally thought that the output of by20Incrementer() would start from 50, but it starts from 0. So the runningTotal of each incrementer refers to different one.

Upvotes: 2

Views: 823

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

Captures do not become static in a closure, in the sense that each instance of the closure gets its own copy of the variable.

I originally thought that the output of by20Incrementer() would start from 50, but it starts from 0

It starts from the value of runningTotal at the time the closure is created, which is always zero. No matter how many times you increment runningTotal in by10Incrementer, it wouldn't change the value of runningTotal captured in by20Incrementer, because it is a different instance with its own capture of runningTotal.

Effectively, runningTotal becomes a var on the object that represents the closure. Swift syntax makes this capture implicit, but internally the variable is there.

Upvotes: 4

Related Questions