(let ([x (call/cc (lambda (k) k))])
(x (lambda (ignore) "hi"))) => "hi"
我该如何编写这个延续的执行步骤?
(let ([x (call/cc (lambda (k) k))])
(x (lambda (ignore) "hi"))) => "hi"
我该如何编写这个延续的执行步骤?
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 和应用程序的知识。
在第一行[x (call/cc (lambda (k) k))]
中,我们创建了一个新的延续,它绑定到k
接收的参数lambda
。它k
被返回并反过来绑定到x
局部变量 - 因此,x
它是一个延续。
在第二行中,x
使用单个参数调用lambda
;参数被忽略,调用的结果(lambda (ignore) "hi")
是"hi"
,最终作为延续的结果返回。这相当于简单地调用:
(call/cc
(lambda (k)
(k "hi")))
为什么这个表达式的计算结果为 "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))
延续都与. 这总是有点棘手。k
call/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"