Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference type in Swift - reference to a function/closure

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:

  1. Because referenceA is a reference to originalFunction(), when I do let referenceB = referenceA , referenceB and referenceA will share the returnValue.
  2. But when I do let referenceC = originalFunction(), in which case I suppose referenceC and referenceA should also share the returnValue since they both refer to originalFunction(), this is not true.

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    
like image 584
Macondo Avatar asked Oct 11 '25 22:10

Macondo


1 Answers

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 vars 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.

like image 171
Marcus Avatar answered Oct 15 '25 06:10

Marcus