Scheme - 转换为continuation-passing风格

时间:2011-11-10 04:30:38

标签: scheme continuations

我有点了解如何将基本功能(如算术)转换为继续传递样式。  但是如果函数涉及递归怎么办? 例如,

(define funname 
     (lambda (arg0 arg1)
                (and (some procedure)
                      (funname (- arg0 1) arg1))))

请给我建议。 提前谢谢。

3 个答案:

答案 0 :(得分:4)

一个对延续和CPS有很好解释的地方是Krishnamurthi的PLAI书。相关部分(VII)不依赖于本书的其他部分,因此您可以直接跳到那里。特别是一个扩展的例子,手动将代码转换为CPS,并处理递归函数(第17章的第一部分)。

另外,我为我的课写了extended version该文本,其中有更多关于这个主题的例子和更多细节 - 你可能会发现它也很有用。除了PLAI文本之外,我还介绍了继承的一些常见用法,例如实现生成器,模糊运算符等等。 (但请注意,PLAI继续讨论实施策略,我的文本没有涉及。)

答案 1 :(得分:1)

(define (func x y k)
  (some-procedure
   (lambda (ret)
     (if ret
         (- x 1
            (lambda (ret)
              (func ret y k)))
         (k #f))))

您缺少基本情况,这就是为什么对延续的唯一显式调用是(k #f)。如果你有一个基本案例,那么你也将基本案例的返回值传递给续集。例如:

(define (func x y k)
  (zero? x
         (lambda (ret)
           (if ret
               (k y)
               (some-procedure
                (lambda (ret)
                  (if ret
                      (- x 1
                         (lambda (ret)
                           (func ret y k)))
                      (k #f))))))))

答案 2 :(得分:1)

这部分重复Chris Jester-Young的答案,但是,我希望我能更好地解释它: - )。

在CPS中,您所寻求的差异在于这两件事(大致):

  • 您可以调用一个过程,并将传递给您的继续传递给它。这相当于直接式优化尾部调用。
  • 或者,您可以调用一个过程,并在其继续中传入一个新的过程,该过程执行“返回值”,并传入原始的继续。这相当于直接式堆栈调用。

后者就是克里斯的例子中的lambdas正在做的事情。基本上,评估lambda会创建一个闭包 - 这些闭包用于执行堆栈框架在执行直接式程序时所做的相同工作。代替堆栈帧中的返回地址,闭包包含一个连续函数的绑定,闭包的代码调用它。