Functional programming 调用延续与函数调用 让我们考虑一个阶乘函数的简单例子,用伪类CPS样式编写(中间结果的枚举和排序将被忽略),即:“非常嘈杂”:

Functional programming 调用延续与函数调用 让我们考虑一个阶乘函数的简单例子,用伪类CPS样式编写(中间结果的枚举和排序将被忽略),即:“非常嘈杂”:,functional-programming,continuations,Functional Programming,Continuations,调用延续(K1)(即“返回”一个值)在技术上是否与“正常”函数调用(如else分支)有所不同?我想到的一件事是,在这种情况下,续集是唯一在其参数中没有另一个续集的东西:) 此外,您是否可以说此计算类似于动态构造树的DFS树漫游,当前计算是当前探索的节点,“其他未探索的分支”是调用堆栈/延续 好吧,你已经回答了你的第一个问题:技术上的区别是没有更多的连续性:这是建立在这一点上的张力被释放的点,也就是说,累积的计算将实际执行[通过一系列的beta减少]。 当然,从语言语义的角度来看,这是一个普通的函

调用延续(K1)(即“返回”一个值)在技术上是否与“正常”函数调用(如else分支)有所不同?我想到的一件事是,在这种情况下,续集是唯一在其参数中没有另一个续集的东西:)


此外,您是否可以说此计算类似于动态构造树的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