Functional programming 调用延续与函数调用 让我们考虑一个阶乘函数的简单例子,用伪类CPS样式编写(中间结果的枚举和排序将被忽略),即:“非常嘈杂”:
调用延续(K1)(即“返回”一个值)在技术上是否与“正常”函数调用(如else分支)有所不同?我想到的一件事是,在这种情况下,续集是唯一在其参数中没有另一个续集的东西:)Functional programming 调用延续与函数调用 让我们考虑一个阶乘函数的简单例子,用伪类CPS样式编写(中间结果的枚举和排序将被忽略),即:“非常嘈杂”:,functional-programming,continuations,Functional Programming,Continuations,调用延续(K1)(即“返回”一个值)在技术上是否与“正常”函数调用(如else分支)有所不同?我想到的一件事是,在这种情况下,续集是唯一在其参数中没有另一个续集的东西:) 此外,您是否可以说此计算类似于动态构造树的DFS树漫游,当前计算是当前探索的节点,“其他未探索的分支”是调用堆栈/延续 好吧,你已经回答了你的第一个问题:技术上的区别是没有更多的连续性:这是建立在这一点上的张力被释放的点,也就是说,累积的计算将实际执行[通过一系列的beta减少]。 当然,从语言语义的角度来看,这是一个普通的函
此外,您是否可以说此计算类似于动态构造树的DFS树漫游,当前计算是当前探索的节点,“其他未探索的分支”是调用堆栈/延续 好吧,你已经回答了你的第一个问题:技术上的区别是没有更多的连续性:这是建立在这一点上的张力被释放的点,也就是说,累积的计算将实际执行[通过一系列的beta减少]。 当然,从语言语义的角度来看,这是一个普通的函数应用程序 至于第二个问题,我可能理解错了,但我要说的是,每一次计算都是一次向叶树行走,但树不是动态构造的,而是程序定义的静态(通常是无限)对象。但是,调用堆栈(即使它很小,因为尾部调用)是您已经经历过的(从根节点到当前节点),而延续是您未来的路径,从应用延续到某个点(即,当您应用此事实函数时,下一个节点再次是事实,除非n为0) 如果您喜欢朝这些方向思考,您可能会喜欢阅读有关流程树的内容,例如。 哈特克利夫的《在线和离线部分评估简介》——顺便说一句,体育课的话题非常有趣), 也许你会喜欢(至少前20页左右)斯科特的“流程图格”(实际上,这篇文章将“更自然”翻译成了应用函数式语言)
希望这能给你一些启示。继续下去的意义在于它们不会回来。它们是
Goto
,而不是Call
。没有区别,这只是一个常规函数。
(def (fact n k) (if (eq? n 0) (k 1) (fact (- n 1) (\result (k (* n result))))))
(fact _ id)
/ \
(= _ 0)? otherwise
| \
(id 1) (fact _ (λ (x) (id (* 2 x))))
| / \
1 (= _ 0)? otherwise
| \
(id (* 2 1))) (fact _ (λ (x) (id (* 2 (* 1 x)))))
| / \
(id 2) (= _ 0)? otherwise
| | \
2 (id (* 2 (* 1 1))) ...
|
(id (* 2 1))
|
(id 2)
|
2