4
(let ([x (call/cc (lambda (k) k))])
    (x (lambda (ignore) "hi")))  => "hi"

我该如何编写这个延续的执行步骤?

4

3 回答 3

7

call/cc运算符用于调用具有当前延续的给定过程(因此名称为call-with-current-continuation)。所以要理解它是如何工作的,我们需要知道当前的延续是什么。

在您的程序中,在call/cc执行时,延续看起来像这样:

CONT = (let ([x HOLE])
         (x (lambda (ignore) "hi")))

whereHOLE是要插入的值的占位符。换句话说,延续是剩余的计算。如果你想进步,你可以在延续中加入一个价值。

现在,call/cc捕获此延续并将其传递给过程(lambda (k) k)。你可以看到这个过程只是立即返回延续。所以程序简化为:

(let ([x CONT])
  (x (lambda (ignore) "hi")))

应用由 捕获的延续call/cc将当前计算替换为插入您给它的值的延续。所以应用程序(x (lambda (ignore) "hi"))变成:

(let ([x (lambda (ignore) "hi")])
  (x (lambda (ignore) "hi")))

其余的应该遵循您已经了解的有关 lambda 和应用程序的知识。

于 2012-07-01T18:54:42.833 回答
3

在第一行[x (call/cc (lambda (k) k))]中,我们创建了一个新的延续,它绑定到k接收的参数lambda。它k被返回并反过来绑定到x局部变量 - 因此,x它是一个延续。

在第二行中,x使用单个参数调用lambda;参数被忽略,调用的结果(lambda (ignore) "hi")"hi",最终作为延续的结果返回。这相当于简单地调用:

(call/cc
 (lambda (k)
   (k "hi")))
于 2012-07-01T19:23:41.250 回答
1

为什么这个表达式的计算结果为 "hi" ?

(let ([x (call/cc (lambda (k) k))])
  (x (lambda (ignore) "hi")))

第一步是决定是什么k样子:

(define k
  (lambda (value)
    (let ((x value))
      (x (lambda (ignore) "hi")))))

我们立即看到这与

(define k
  (lambda (x)
    (x (lambda (ignore) "hi"))))

但是,我没有提到一个小细节。如果k曾经被调用,就好像它是在尾部位置调用的。

因此,对于所有由 构建的(f (k 3))延续都与. 这总是有点棘手。kcall/cc(k 3)

所以,我们用lambda^来表示它引入的函数将被调用,就好像它在尾部位置一样。

(define k
  (lambda^ (x)
    (x (lambda (ignore) "hi"))))

现在我们知道了k是什么,我们还需要知道,返回(call/cc (lambda (k) k))实际上是使用默认值。

它应该正确地写为

(call/cc (lambda (k) (k k))).

在传递给 的 lambda 表达式主体的顶部总是隐含调用 k call/cc

我们知道是什么k

因此,我们知道这必须与,(为了便于阅读,让我们将x参数位置中的 's 变成y's。)

((lambda^ (x) (x (lambda (ignore) "hi")))
 (lambda^ (y) (y (lambda (ignore) "hi"))))

因此,我们将这两个位置都评估为函数。

一旦我们在函数位置调用函数,我们就完成了,因为它以 So 为首lambda^ ,我们需要知道

((lambda^ (x) (x (lambda (ignore) "hi")))
 (lambda^ (y) (y (lambda (ignore) "hi"))))

计算为,代入x

((lambda^ (y) (y (lambda (ignore) "hi")))
 (lambda (ignore) "hi"))

还有一步,代替y

导致

((lambda (ignore) "hi") (lambda (ignore) "hi")), 它忽略它的参数并返回 "hi"

于 2012-08-27T16:51:43.120 回答