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.
3 Likes
SDGGiesbrecht
(Jeremy David Giesbrecht)
3
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.
SDGGiesbrecht
(Jeremy David Giesbrecht)
4
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?
1 Like
orchetect
(Stef)
5
Closures are meant to be blocks of functionality, they don't hold stored state or properties. So I'm also curious what the intention of OP is.
cukr
6
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
2 Likes
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"
See Documentation for more information.
3 Likes