Reputation: 369
I noticed that in Swift, when I create an originalFunction() with a return value returnValue, and make a new function let referenceA = originalFunction(), this will happen:
Why?
Example:
func makeIncrementor(forIncrement amount:Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
//then let's make referenceA
let incrementByTen = makeIncrementor(forIncrement:10)
incrementByTen()
//returns 10
incrementByTen()
//returns 20
//Now make referenceB
let incrementBy10 = incrementByTen
//referenceA and referenceB will share the *returnValue*:
incrementBy10()
//returns 30
//Now make referenceC
let incrementByTen10 = makeIncrementor(forIncrement:10)
//referenceA and referenceC do not share the *returnValue*
incrementByTen10()
//returns 10
Upvotes: 4
Views: 1341
Reputation: 828
Your makeIncrementor
function creates a new () -> Int
incrementor function that captures the runningTotal
variable that you create right above it. Because closures are reference types when you assign your incrementByTen
closure to the new incrementBy10
closure, you are really just assigning a reference and each of these var
s are pointing to the same closure, so calling either of these will increment the same runningTotal
var
that the closure captured.
When you call makeIncrementor
a second time, it creates a new closure that captures a new runningTotal
var
, so it does not share the same runningTotal
with the first closure you created.
Your incrementor
func
is not shared because you declare it inside of makeIncrementor
, so it is only alive for the scope of that calling of makeIncrementor
and will be redeclared as a new func
the next time makeIncrementor
is called. If you wanted this to be shared every time you called makeIncrementor
, your incrementor
func
would need to be declared outside of makeIncrementor
.
Upvotes: 4
Reputation: 2193
If my understanding is correct, this is because nested functions are a mere syntactic sugar to create closures, so another instance of incrementor
is created every time makeIncrementor
is called.
Your code above is nearly identical to this.
func makeIncrementor(forIncrement amount:Int) -> () -> Int {
var runningTotal = 0
let incrementor = {
runningTotal += amount
return runningTotal
}
return incrementor
}
Upvotes: 0