我似乎无法将我的想法包含在Scheme中的call / cc中

时间:2011-03-14 17:51:15

标签: scheme call continuations callcc

有没有人对如何运作有一个很好的指导?带有视觉辅助工具的东西会很好,我遇到的所有指南似乎都说同样的东西我需要一个新的东西。

5 个答案:

答案 0 :(得分:11)

这是我们CS实验室白板上留下的图表。所以你要取一些苹果,然后在开始之前抓住一个延续。你漫步在森林里,收集苹果,最后你在苹果上继续施用。突然间,你在进入森林之前就已经找到了自己的位置,除了你所有的苹果

call/cc

(display
  (call/cc (lambda (k)
             (begin
               (call-with-forest
                 (lambda (f)
                   (k (collect-apples f))))
               (get-eaten-by-a-bear)))))

=> some apples (and you're not eaten by a bear)

我认为可能涉及到成年礼和埋藏的黄金。

答案 1 :(得分:5)

看一下PLAI的延续部分 - 它非常“实用” 面向“,它使用”黑洞“可视化为可以帮助您的延续 理解它。

答案 2 :(得分:0)

学习call / cc没有捷径。阅读The Scheme Programming LanguageTeach Yourself Scheme in Fixnum Days中的章节。

答案 3 :(得分:0)

我发现可视化调用堆栈很有帮助。在计算表达式时,请在每个步骤跟踪调用堆栈。 (参见例如http://4.flowsnake.org/archives/602)这可能一开始并不直观,因为在大多数语言中,调用堆栈是隐含的;你不能直接操纵它。

现在将延续视为保存调用堆栈的函数。当调用该函数(值为X)时,它会恢复保存的调用堆栈,然后将X传递给它。

答案 4 :(得分:0)

永远不喜欢call / cc的直观表示,因为我无法将其反映回代码(是的,想象力差);)

无论如何,如果您已熟悉其他语言的例外情况,我认为如果您已经熟悉其他语言的例外情况,那么不要使用call / cc,而是使用call / ec(escape continuation)更容易。

以下是一些应该评估为值的代码:

(lambda (x) (/ 1 x))

如果x等于'0'怎么办?在其他语言中我们可以抛出异常,那么方案呢? 我们也可以扔掉它!

(lambda (x) (call/ec (cont) 
 (if (= x 0) (cont "Oh noes!") (/ 1 x))))

call / ec(以及call / cc)就像“尝试”一样。在命令式语言中,您可以轻松跳出函数,只返回值或抛出异常。 在功能上你不能跳出来,你应该评价一些东西。并致电/ *来救援。 它的作用是将“call / ec”表示为函数(在我的例子中,这个名称为“cont”),带有一个参数。调用此函数时,它会将WHOLE调用/ *替换为它的参数。

因此,当(cont "Oh noes!")(call/ec (cont) (if (= x 0) (cont "Oh noes!") (/ 1 x)))替换为"Oh noes!"字符串时。

call / cc和call / ec几乎等于彼此,除了ec更简单的实现。它只允许跳起来,可能会从外面跳下来。