【问题标题】:how does call/cc jump from two subrutinecall/cc 如何从两个子程序中跳转
【发布时间】:2017-08-01 16:33:47
【问题描述】:

我写了一个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);
    }
}

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

【问题讨论】:

    标签: scheme callcc


    【解决方案1】:

    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)
    

    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”。

    【讨论】:

      猜你喜欢
      • 2019-12-30
      • 2015-02-09
      • 2011-02-16
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 2020-01-06
      • 2019-12-17
      • 1970-01-01
      相关资源
      最近更新 更多