swift - 在 Swift 中实现 Y-Combinator
问题描述
我正在观看 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 的静态类型而这不可能?
解决方案
推荐阅读
- reactjs - 从导入的自定义组件中检索道具值
- camunda - 如何在 camunda 上启用 CustomRetryHandler
- angular - 使用 jQWidgets 和 Karma/Jasmine 对 Angular 应用程序进行单元测试
- android - 根据给定的数据在特定日期安排工作
- android - 在 RecyclerView 上带有 ItemTouchHelper 的 Android 房间。清洁实施?
- angular - 从子组件角度访问父变量
- python - 列表索引超出范围 - 具有一个元素的 Python 列表
- javascript - 正则表达式:类似 Slack 的“markdown”,用于精确匹配一个格式字符
- bash - 在 JSON 值中带有反引号的 jq 脚本
- html - html/css,让按钮看起来像一个 div