1

我在 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);
    }
}

所以我的意见有什么问题?

4

1 回答 1

1

call/cc将程序重写为继续传递样式。我稍微更改了代码以显示结果并在之后添加了一个附加代码,以便您掌握它,这是我的修改:

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

在 CPScall/cc中仅此而已:

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

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

我定义了一个 CPS 版本display和最终的延续函数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 中,评估顺序取决于这种形式的实现,顺序将非常清楚地显示出来。请注意,它永远不会返回,只是在尾部位置调用延续:

; 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)))))

现在,如果您逐步执行此操作,很明显为什么它从不显示“2”。

于 2017-03-11T11:00:15.927 回答