方案,电话/ cc

时间:2012-07-25 02:36:14

标签: scheme continuations callcc

因此,我试图弄清楚Scheme中的整个call/cc事物。以下是我正在使用的代码:

(+ 1 (call/cc
  (lambda (k)
    (if (number? k)
        (call/cc (lambda (k) (k (- 1 k))))
        (k 4)))))

所以我们在这里开始在第一个括号中添加两个参数。 1以及由于热切评价我们必须评估的其余部分。所以我们有一个call/cc接受一个参数,一个函数,call/cc通过调用来评估。 (我是对的吗?)与此同时,它在我们的第一个括号中保留了迄今为止发生的其余部分,即(+ 1 []),这是“延续”。 (我是对的?)所以我们将lambda k称为继续,如我刚才所述,(+ 1 [])。在函数中它然后询问这是否是一个数字,它不是并且是“然后”。我在这里“迷失”了,这第二个call/cc做了什么?调用(k 4)是什么,使整个事情评估为5

2 个答案:

答案 0 :(得分:3)

你很亲密!我认为你的所有问题都是正确的。

传递给call/cc的函数接受一个参数(在您的示例中为k),这是一种将值返回到当前延续的方法。 k是一个参数的函数。当您使用某个值调用该函数时,该值将返回并代替_中的(+ 1 _)

因此,在您的示例中,(number? k)永远不会成立,并且永远不会执行对call/cc的第二次调用。 (即使它是,它会因运行时错误而失败,其中(- 1 k)从1中减去一个函数。)因此它实际执行“else”分支:(k 4),它返回4到{{1}所以结果是5。

希望这很清楚!

答案 1 :(得分:1)

call/ccsetjmp类似。它定义了一个退出点,后面的代码可以直接“跳转”到,如longjmp那样。

它遵循一定的协议,所以我们总是写

( .... surrounding code .....
   (call/cc (lambda (k)
      .... inner code which has access to the exit point "k" ....
      )) .... more surrounding code .... )

在该协议下,“内部”代码照常执行,但在其范围内也有一个名称k。没有任何“周围”代码可以访问它,因为它超出了k的范围。

k这是一个第一类值(当然,因为它被命名)。 Scheme运行时系统将在幕后自动为其分配(call/cc ...)呼叫点的延续。对于程序员,只要我们有权访问它,我们就可以使用它。

延续是一个参数的函数。当调用该函数时,它会将其参数传递给continuation的调用上下文。但由于k是一流的命名值,我们可以自由传递它。 “内部”代码可以像我们想要的那样复杂,它可以调用其他地方定义的其他函数等。如果它将k作为参数传递给这样的外部函数,它也可以使用它。

使用值调用k表示将该值返回到原始(call/cc ...)调用的调用上下文中。的 直接 即可。就像longjmp那样(除了我们可以在那里返回任何值,而不仅仅是int)。