我正在观看 Jim Weirich 的演讲:https ://www.youtube.com/watch?v=FITJMJjASUs关于在 Ruby 中实现 Y-Combinator,并在 Swift 中跟进。
我最终得到了这个函数,它可以作为高达 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-combinator?还是因为 Swift 的静态类型而这不可能?