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"