My understanding is that closures are reference types, so doing something like the following will result in both constants referring to the same instance of the closure:
let closureA = { print("I'm in a closure") }
let closureB = closureA
In Obj-C I believe there was a way to make a copy of a block.
Is there a way to make a copy of a closure in Swift?
The copying mechanism in ObjC is just for getting the block off the stack; once itβs off the stack, βcopyingβ just retains the existing value. That detail is something that Swift hides from you.
Closure variables have value semantics. (But are presumably only copyβonβwrite like structures.)
var closure: (Int) -> Void = { print("\($0): Iβm still the first closure.") }
closure(1) // 1: Iβm still the first closure.
var newVariable = closure
newVariable(2) // 2: Iβm still the first closure.
closure = { print("\($0): Iβve been mutated.") }
closure(3) // 3: Iβve been mutated.
newVariable(4) // 4: Iβm still the first closure.
On second thought, thatβs not really mutation but reassignment.
Since closures arenβt mutable in the first place, Iβm not sure what difference it makes, or why you would need a copy instead of a reference. What is it you are trying to do?
That's not true, they do hold state and that state isn't copied when you copy the closure itself. Check out this snippet:
func giveMeAClosureThatHoldsState() -> ( (Int) -> Int ) {
var state = 0
return { difference in
state += difference
return state
}
}
let closureWithState = giveMeAClosureThatHoldsState()
let closureCopy = closureWithState
let anotherClosureWithState = giveMeAClosureThatHoldsState()
print(closureWithState(1)) // prints 1
print(closureWithState(1)) // prints 2
print(closureCopy(1)) // prints 3
print(anotherClosureWithState(1)) // prints 1
As others have explained above, closures don't really copy.
Yet there is a closure feature which is somewhat related: the capture list.
The capture list allows a closure to copy the values of captured variables, and this makes a big difference when captured variables are mutable. Compare:
var value = 0
let closure1 = { return value }
let closure2 = { [value] in return value }
print("closure1: \(closure1())") // prints "closure1: 0"
print("closure2: \(closure2())") // prints "closure2: 0"
value = 42
print("closure1: \(closure1())") // prints "closure1: 42"
print("closure2: \(closure2())") // prints "closure2: 0"
I guess you meant to say "they do hold state and state is copied when you copy the closure itself" -> print(closureWithCopy(1)) results in "3" as opposed to "2" (which imo would mean the state isn't copied) ?
Here's what going on after each line. Notice how both closureWithState and closureCopy point to the same state, so calling closureWithState changes what closureCopy returns