0

私は、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) -> Intgenerator

代わりに、次のように 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 の静的型付けのためにこれは不可能ですか?

4

0 に答える 0