6

有人对它的工作原理有很好的指导吗?带有视觉辅助的东西会很好,我遇到的每一个指南似乎都在说同样的事情,我需要重新审视它。

4

5 回答 5

11

这是我们 CS 实验室白板上留下的图表。所以你要取一些苹果,然后在开始之前抓住一个延续。您在森林中漫步,收集苹果,最后您将延续应用到苹果上。突然,你发现自己在进入森林之前所处的位置,除了你所有的苹果

致电/抄送

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

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

于 2011-03-15T01:48:15.320 回答
5

Have a look at the continuation part of PLAI -- it's very "practical oriented", and it uses a "black-hole" visualization for continuations that can help you understand it.

于 2011-03-14T17:57:07.283 回答
0

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

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

于 2012-03-31T09:22:20.310 回答
0

学习 call/cc 没有捷径可走。阅读方案编程语言中的章节或在 Fixnum Days 中自学方案

于 2011-03-15T09:50:08.477 回答
0

从不喜欢 call/cc 的可视化表示,因为我无法将其反映到代码中(是的,想象力很差);)

无论如何,如果您已经熟悉其他语言的异常,我认为不从 call/cc 而是从 call/ec(转义继续)开始会更容易。

这是一些应该评估为价值的代码:

(lambda (x) (/ 1 x))

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

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

call/ec(以及 call/cc)在这里的工作方式类似于“try”。在命令式语言中,您可以轻松地跳出函数,只需返回值或抛出异常。在功能上你不能跳出来,你应该评估一些东西。并且 call/* 来救援。它的作用是将“call/ec”下的表达式表示为带有一个参数的函数(在我的例子中称为“cont”)。当这个函数被调用时,它会将整个调用 /* 替换为它的参数。

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

call/cc 和 call/ec 几乎相等,除了 ec 更易于实现。它只允许跳上去,而cc可以从外面跳下来。

于 2012-04-10T14:01:23.720 回答