调用延续与函数调用

时间:2016-08-05 06:39:33

标签: functional-programming continuations

让我们考虑一个阶乘函数的简单例子,用类似伪CPS的方式编写(省略中间结果的枚举和排序,因为它会非常嘈杂):

(def (fact n k) (if (eq? n 0) (k 1) (fact (- n 1) (\result (k (* n result))))))

调用延续(k 1)(即"返回"值)在某种程度上在技术上不同于"正常"函数调用,如在else-branch中?我想到的一件事是,在这种情况下,延续是唯一没有另一个延续的东西:)

另外,你能说这个计算类似于动态构造的树的DFS树步行,当前计算是当前探索的节点和其他未探索的分支"是一个调用栈/继续?

1 个答案:

答案 0 :(得分:1)

嗯,你已经回答了你的第一个问题:技术上的差异是没有更多的传递延续:这就是这一点产生的张力被释放的地方,即积累的计算将会发生的地方实际上[通过一系列β减少]进行。 当然,从语言的语义来看,这是一个普通的函数应用程序。

截至第二个问题,我可能理解你错了,但是我说每个计算都是叶子树步行,但树不是动态构造的,而是静态的(通常是无限的)对象[uniquiely]由程序定义。但是,调用堆栈[即使它因为尾调用而变得微不足道]是你已经走过的(从根到当前节点),而延续是你未来的道路,从应用延续的角度来看某事(即当你正在应用这个事实函数时,下一个节点再次成为事实,除非n为0)。

  (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

如果您喜欢在这些方向上思考,您可能希望了解有关过程树的信息。 Hatcliff"在线和离线部分评估简介" http://repository.readscheme.org/ftp/papers/pe98-school/hatcliff-DIKU-PE-summerschool.pdf - 顺便说一下PE的主题很有意思,), 也许你可能会喜欢(至少前20页左右)斯科特"莱迪思的流程图" (https://www.cs.ox.ac.uk/files/3223/PRG03.pdf - 实际上,这篇论文翻译了“更自然的”和“应用函数式语言”。

希望能给你一些见解。