Reputation:
When I create a constant to put my closure to work:
let incrementByTen = makeIncrementer(forIncrement: 10)
Does it skip incrementer() until it's called in the return statement, that way the return statement can run the incrementer() function in the end and receive its value?
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
Upvotes: 0
Views: 708
Reputation: 53000
In a comment you have extended your question with:
I've read that this function captures a reference to runningTotal and amount. What's hard to grasp is how it keeps increasing when I repeatedly call incrementByTen().
The function incrementer
captures the value of amount
and the variable runningTotal
. Capturing a value just involves copying the value into the function value (aka closure).
Capturing the variable is more involved: as a local variable runningTotal
's lifetime would usually only extend at most to the end of the function invocation it is created by - so a call to makeIncrementer
would create a new local runningTotal
and when that call returned the variable would be destroyed. However as runningTotal
is captured as a variable by incrementer
then its lifetime is automatically extended as long as it is required by incrementer
, which is as long as incrementer
itself is required. As incrementer
is the value returned by makeIncrementer
the lifetime of runningTotal
extends past the lifetime of the call to makeIncrementer
.
Later each time the function returned by a single call to makeIncrementer
is invoked as it has captured the variable runningTotal
from that call it is incremented by 10 and its current value returned.
If you call makeIncrementer
twice and store both results, then each result references a distinct function and each of those functions references a distinct variable - so you have two distinct incrementing counters.
HTH
Upvotes: 0
Reputation: 41226
The arguments to a function are evaluated when the function is called. In this case that means that when makeIncrementer
is called, it's argument (10 in this case) will be evaluated before makeIncrementer
is actually called.
Likewise, when makeIncrementer
is invoked, it's code will be executed in sequence, initializing runningTotal
and then initializing incrementer
(note that at this point amount
has been evaluated already, so in the returned incremented, it is ALWAYS 10.
Subsequently, when you invoke incrementByTen()
there are no arguments to pass and nothing to be evaluated before the call, as part of executing the closure, runningTotal will be incremented by amount, in this case, always 10.
Upvotes: 0