Reputation: 2811
If i write a block example like this
var i = 0
var allBlocks :[()->()] = []
for i in 1...5 {
var block:() -> () = {print(i)}
allBlocks.append(block)
}
for var block2:() -> () in allBlocks {
block2()
}
and the out put will be
1
2
3
4
5
but if i write like this
var i = 0
var allBlocks :[()->()] = []
for _ in 1...5 {
var block:() -> () = {print(i)}
allBlocks.append(block)
i += 1
}
for var block2:() -> () in allBlocks {
block2()
}
the output will be
5
5
5
5
5
seems the second example the block capture the i as reference ,and in the first example the i is capture by value ? what's the thing behind the difference of these examples?
Upvotes: 0
Views: 236
Reputation: 154583
Both examples are capturing references to a variable named i
. In your first example where i
is the loop variable, there are actually 5 separate variables each named i
. Each loop has its own variable named i
.
Consider this extended example where we capture each variable twice in the loop:
var allBlocks: [()->()] = []
var multBlocks: [()->()] = []
for var i in 1...5 {
let block = { print(i) }
let multblock = { i *= 10 }
allBlocks.append(block)
multBlocks.append(multblock)
}
for (block, multblock) in zip(allBlocks, multBlocks) {
block()
multblock()
block()
print("-----")
}
Output
1 10 ----- 2 20 ----- 3 30 ----- 4 40 ----- 5 50 -----
zip
pairs up the block
and multblock
closures, and each loop operates on a single pair.
The multblock
closure mutates the captured variable, and the output clearly demonstrates that there are 5 different variables that have been captured, and it demonstrates that the variables are being captured as a reference (not by value) since the block
and multblock
closure pairs are clearly accessing the same value of i
.
In your second example, all of the closures capture the same single i
variable, and they all run after it has been incremented to 5
.
Upvotes: 3
Reputation: 54706
The difference comes from the scope of your variables. In your first example, i
is declared in the for...in
loop and hence its scope is local to the loop. Hence, when passed to a closure, it needs to be passed to the closure inside the loop when the closure is created.
On the other hand, in your second example, i
is declared as a mutable variable outside the loop, so it doesn't need to be passed to the closure at the time the closure is created, it can be evaluated when the closure itself is executed. This couldn't be done in your first example, since i
no longer exists by the time you evaluate your closure outside the for...in
loop.
Your declaration of var i = 0
is misleading in your first example, since that variable won't actually be used, the local variable declared in the for i in 1...5
loop will be used instead.
Upvotes: 1