Update: I tried writing it without making it weak, and there doesn't seem to be a leak. So maybe the question is no longer necessary.
In Objective-C ARC, when you want to have a closure be able to use itself inside of the closure, the block cannot capture a strong reference to itself, or it will be a retain cycle, so instead you can make the closure capture a weak reference to itself, like so:
// This is a simplified example, but there are real uses of recursive closures
int (^fib)(int);
__block __weak int (^weak_fib)(int);
weak_fib = fib = ^(int n) {
if (n < 2)
return n;
else
return weak_fib(n-1) + weak_fib(n-2);
};
I tried to translate this to Swift:
var fib: (Int -> Int)?
fib = { [weak fib] (n: Int) in // 'weak' cannot be applied to non-class type 'Int -> Int'
if n < 2 {
return n
} else {
return fib!(n-1) + fib!(n-2)
}
}
However, the Swift compiler won't allow me to declare a function to be captured weakly ('weak' cannot be applied to non-class type 'Int -> Int'
). [unowned fib]
also doesn't work ('unowned' cannot be applied to non-class type '(Int -> Int)?'
).
I know that functions are not class types in Swift. However, they are reference types and they do participate in reference counting. Therefore, shouldn't there be a way to make them weak or unowned references?
How would I write a recursive closure in Swift that doesn't have a retain cycle?
Note: The declaration of a property is strong by default. To declare a weak reference we use the weak keyword. In Swift, whenever we create an instance of a class, a reference count value is increased from 0 to 1. Similarly, if we dellocate the instance the count is decreased to 0. Let's see an example,
In Swift, a closure captures its context. This means it strongly references anything referred to inside of it. If you have a closure that belongs to a class, and you call self inside that closure, you create a strong reference cycle.
In Swift, a closure captures its context. This means it strongly references anything referred to inside of it. If you have a closure that belongs to a class, and you call self inside that closure, you create a strong reference cycle. The closure strongly references to self. And self (the class) strongly references to the closure.
In Swift, [weak self] prevents closures from causing memory leaks in your application. This is because when you use [weak self], you tell the compiler to create a weak reference to self. In other words, the ARC can release self from memory when necessary.
Looks like this isn't possible at the moment; you might want to file a bug.
But you can use an actual func
tion to achieve the same thing:
func fib(n: Int) -> Int {
if n < 2 {
return n
} else {
return fib(n-1) + fib(n-2)
}
}
fib(10) // 55
Computer science fun time! For a more direct translation of your code, we can use the Z combinator, with help from Swift's built-in curried function definitions:
func Z<T, U>(f: (T -> U, T) -> U)(x: T) -> U {
return f(Z(f), x)
}
let fib = Z { (fib: Int -> Int, n: Int) in
if n < 2 {
return n
} else {
return fib(n-1) + fib(n-2)
}
}
fib(x: 10) // 55
// (Note the name 'x' should not be required here.
// It seems seems to be a bug in Beta 3, since the curried function in the
// Swift guide doesn't work as advertised either.)
It looks like there is no way to declare weak/unowned reference to the function; at lest for now. As workaround you can wrap your code in a class definition and have unowned
reference to the instance:
class Fib {
@lazy var calc:(Int) -> Int = {
[unowned self] (n: Int) -> Int in
if n < 2 {
return n
} else {
return self.calc(n-1) + self.calc(n-2)
}
}
}
Usage:
let f = Fib()
let result = f.calc(6)
The problem is well described here:
https://xiliangchen.wordpress.com/2014/08/04/recursive-closure-and-y-combinator-in-swift/
In short:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With