私は、Jim Weirich による次の講演を見ていました。
最終的に、5 までの階乗として機能するこの関数にたどり着きました。
let error: (Int) -> Int = { x in return -1 }
let generator = { (generator: (@escaping ((Int) -> Int)) -> (Int) -> Int) in
generator(generator(generator(generator(generator(generator(error))))))
}( { (factorial: @escaping ((Int) -> Int)) -> (Int) -> Int in
{ (x: Int) -> Int in
if x == 0 { return 1 }
return x * factorial(x-1)
}
}
)
次に何が起こるかというと、彼が を削除error
しても、彼のコードは引き続き機能します。
let generator = { (generator: (@escaping ((Int) -> Int)) -> (Int) -> Int) in
generator(generator)
} ...
これは、Swift では、入力としてgenerator
期待されているが型を取得しているため、コンパイラの失敗です。(Int) -> Int
generator
代わりに、次のように Y コンビネータを実装できます。
func Y<T, R>(_ generator: @escaping (@escaping (T) -> R) -> (T) -> R) -> (T) -> R {
return { (t: T) -> R in
let recursiveWorker = Y(generator)
let worker = generator(recursiveWorker)
return worker(t)
}
}
let factorial = Y { (factorial: @escaping (Int) -> Int) -> (Int) -> Int in
{ (x: Int) -> Int in
if x == 0 { return 1 }
return x * factorial(x-1)
}
}
しかし、上記の問題は、Y
関数が次の行でそれ自体を参照していることです。
let recursiveWorker = Y(generator)
これは、この演習の目的全体を無効にしているように思えます。
私の質問は: Swift で講演と同じコードを実装することは可能ですか? つまり、クロージャ Y コンビネータを作成しますか? それとも、Swift の静的型付けのためにこれは不可能ですか?