呼叫/ cc的细节

时间:2009-07-13 14:49:59

标签: scheme continuations callcc

这与What is call/cc?有关,但我不想为了自己的目的而劫持这个问题,而且它的一些论据就像对setjmp / longjmp的类比一样逃避了我。

我认为我对延续是什么有充分的了解,我认为它是当前调用堆栈的快照。我不想讨论为什么这可能有趣或者你可以用延续做什么。我的问题更具体地说,为什么我必须提供一个函数参数来调用/ cc?为什么不调用/ cc只返回当前的延续,所以我可以用它做任何事情(存储它,调用它,你命名它)?在另一个问题(http://community.schemewiki.org/?call-with-current-continuation-for-C-programmers)的链接中,它谈到“基本上它只是一种干净的方式来延续你并避免后续跳回到保存的点。”但是我我没有得到它。这似乎不必要地复杂。

4 个答案:

答案 0 :(得分:9)

如果你使用类似Jay节目的构造,那么你可以抓住延续,但在某种程度上,抓取的值已经被破坏了,因为你已经在那个延续中。相反,call/cc可用于获取当前表达式之外仍然挂起的延续。例如,continuation最简单的用途之一是实现一种abort

(call/cc (lambda (abort)
           (+ 1 2 (abort 9))))

您无法使用您描述的操作执行此操作。如果你试试:

(define (get-cc) (call/cc values))
(let ([abort (get-cc)]) (+ 1 2 (abort 9)))

然后您收到有关将9应用为过程的错误。发生这种情况是因为abort使用新值let跳回9 - 这意味着您现在正在执行第二轮相同的加法表达式,但现在除了{ {1}}绑定到abort ...

另外两个相关注释:

  1. 有关延续的实用介绍,请参阅PLAI
  2. 9 有点复杂,因为它接受了一个函数 - 概念上更容易使用的构造是call/cc,你可以在PLT Scheme等一些实现中找到它。上面的示例变为let/cc

答案 1 :(得分:2)

那将是不太通用的。如果你想要这种行为,你可以这样做:

(call/cc (lambda (x) x))

你可以看一下“Darrell Ferguson和Dwight Deugo”中延续的例子用法。用当前的继续模式打电话。“。第8届节目模式语言会议。2001年9月。” (http://library.readscheme.org/page6.html)并尝试使用上面定义的call / cc-return重写它们。

答案 2 :(得分:2)

我建议首先问自己:成为一流的延续是什么意思?

表达式的延续基本上由两段数据组成:第一,表达式的闭包(即环境);第二,表达应该对表达式的结果做什么。因此,具有第一类延续的语言是具有封装这些部分的数据结构的语言,并且与其他任何部分一样处理这些数据结构。

call / cc是一种特别优雅的方式来实现这个想法:当前的延续被打包成一个程序,它封装了要用表达式做什么,就像程序在应用时所做的那样。表达方式;以这种方式表示延续只是意味着此过程的闭包包含调用它的站点的环境。

你可以想象以其他方式实现一流延续的想法。他们不会打电话/ cc,我很难想象这样的表现会更简单。

在分页上,考虑Eli提到的let / cc的实现,我更喜欢调用bind / cc:

(define-syntax bind/cc
    (syntax-rules ()
        ((bind/cc var . body)
             (call/cc (lambda (var) . body)))))

作为练习,你将如何实现基于bind / cc的call / cc?

答案 3 :(得分:2)

针对普通的SO网络礼节,我正在回答我自己的问题,但更多的是编辑而不是答案的提供者。

过了一会儿,我在LtU开始了类似的问题。毕竟,这些是那些整天思考语言设计的人,不是他们,其中一个answers终于和我一起开始了。现在这里提到的事情,例如通过Eli或原始问题,对我来说更有意义。这完全取决于延续中包含的内容,以及应用的延续所在的位置。

LtU的posters之一写道:

  

“你可以确切地看到call / cc如何让你”不受阻碍。“使用em或get / cc你需要做一些测试来确定你是否有一个跳跃或只是初始call。基本上,call / cc保持继续使用continuation,而使用get / cc或em,continuation包含它的使用,所以(通常)你需要在continuation的开头添加一个测试(即紧接着get / cc / em)将“继续部分”与“其余的延续部分”分开。“

这让我回家了。

无论如何,谢谢你们!