user3674231
user3674231

Reputation:

What gets executed first in a nested function?

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

Answers (2)

CRD
CRD

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

David Berry
David Berry

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

Related Questions