call / cc如何从两个subrutine跳转

时间:2017-03-11 09:21:52

标签: scheme callcc

我写了一个scheme interpreter in scala,它确实有效,但我仍然无法弄清楚它是如何在子程序之间切换的。 例如:

(call/cc
 (lambda (k)
   (k 1)
   (display 2)))

我认为应该执行显示程序,但它没有。

在java中,它只是这样的东西:

public class Test {

    static void call_cc(Consumer<Consumer> k,Consumer current){
        k.accept(current);
    }

    public static void main(String[] args){
        call_cc(consumer -> {
            consumer.accept(1);
            System.out.println(2);
        },System.out::print);
    }
}

那么我的观点是什么问题?

1 个答案:

答案 0 :(得分:2)

call/cc将程序重写为继续传递样式。我已经稍微更改了代码以显示结果并且之后有一个额外的代码,以便您可以了解它,这是我的修改:

(display (call/cc
 (lambda (k)
   (k 1)
   (display 2))))
(display "finished")

在CPS中call/cc只不过是:

(define (call/cc& f continuation)
  (define (exit value actual-continuation)
    (continuation value))
  (f exit continuation)

退出函数在使用时会得到一个表示CPS中其余程序的闭包,但它的主要功能是使用它自己的连续而不是提供的连续。

我定义了display的CPS版本和最终延续函数halt

; CPS version of display
(define (display& s k)
  (display s)
  (k 'undefined))

; The final continuation
; We make the REPL get the result and it display it
(define halt values)

现在重写代码。 CPS类型将代码更改为在每个步骤中仅计算一件事的步骤过程,而在Scheme中,评估的顺序取决于此形式的实现,订单将非常清楚地显示。请注意,它永远不会返回,只是在尾部位置调用continuation:

; CPS version of the code
(call/cc&
 (lambda (exit continuation)
   (exit 1 
         (lambda (unused)
           (display& 2 continuation))))
 (lambda (value)
   (display& value
             (lambda (unused)
               (display& "finished" halt)))))

现在,如果你逐步完成这一点,很明显为什么它永远不会显示&#34; 2&#34;。