13

更新:弱くせずに書いてみましたが、漏れはないようです。そのため、その質問は不要になったのかもしれません。


Objective-C ARC では、クロージャーをクロージャーの内部で使用できるようにする場合、ブロックはそれ自体への強い参照をキャプチャできません。または保持サイクルになるため、代わりにクロージャー キャプチャを次のように、それ自体への弱参照。

// 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);
};

これを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)
  }
}

ただし、Swift コンパイラでは、関数を弱くキャプチャすることを宣言できません ( 'weak' cannot be applied to non-class type 'Int -> Int')。[unowned fib]も機能しません ( 'unowned' cannot be applied to non-class type '(Int -> Int)?')。

関数は Swift のクラス型ではないことを知っています。ただし、それらは参照型であり、参照カウントに参加します。したがって、それらを弱い参照または所有されていない参照にする方法はありませんか?

Swift で保持サイクルを持たない再帰的クロージャーをどのように記述しますか?

4

4 に答える 4

6

これは現時点では不可能のようです。バグを報告することをお勧めします。

ただし、実際のfuncションを使用して同じことを達成できます。

func fib(n: Int) -> Int {
    if n < 2 {
        return n
    } else {
        return fib(n-1) + fib(n-2)
    }
}

fib(10) // 55

コンピューターサイエンスの楽しい時間!コードをより直接的に変換するには、Swift の組み込みのカリー化された関数定義の助けを借りて Z コンビネーターを使用できます。

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.)
于 2014-07-13T05:48:17.013 に答える
1

関数への弱い/所有されていない参照を宣言する方法がないようです。少なくとも今のところ。回避策として、コードをクラス定義でラップunownedし、インスタンスへの参照を持たせることができます。

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)
        }
    }
}

使用法:

let f = Fib()
let result = f.calc(6)
于 2014-07-13T07:53:07.220 に答える