1

在表达式(call/cc (lambda (k) (k 12)))中,有三个延续:(k 12)(lambda (k) (k 12))(call/cc (lambda (k) (k 12)))。哪一个是“当前的延续”?

在某些书籍中,延续被视为等待一个值的过程,当它应用于一个值时它会立即返回。是对的吗?

谁能详细解释当前的延续?

4

2 回答 2

2

诸如此类的事情(k 12)不是延续。在一些较大的程序中,每个子表达式都有一个延续。例如,xin的延续(* 3 (+ x 42))(lambda (_) (* 3 (+ _ 42)))

在您的示例中,“当前延续”(call/cc (lambda (k) (k 12)))将是围绕该表达式的任何内容。如果您只是将其键入到方案提示符中,则它周围没有任何内容,因此“当前继续”只是(lambda (_) _). 如果您键入类似的内容(* 3 (+ (call/cc (lambda (k) (k 12))) 42)),则继续是(lambda (_) (* 3 (+ _ 42))).

请注意,我用来表示“当前延续”的 lambda 与传入的(在您的示例call/cc中命名)不同。具有特殊的控制效果,即在评估当前继续之后中止其余的计算。kk

于 2012-10-03T20:21:21.430 回答
1

在这种情况下,延续是接收call/cc调用返回值的“事物”。因此:

(display (call/cc (lambda (k) (k 12)))

有相同的结果

(display 12)

Scheme 中的延续“看起来和感觉”类似于过程,但它们实际上并不像过程。可以帮助您更好地理解延续的一件事是 CPS 转换。


在 CPS 转换中,不是函数返回值,而是接受一个延续参数,并使用结果调用延续。sqrt因此,将调用CPS 转换的函数(sqrt 64 k),而不是返回 8,它只是(k 8)在尾部位置调用。

因为延续(在 CPS 转换的函数中)是尾调用的,所以函数不必担心延续返回,事实上,在大多数情况下,它们不会返回。

考虑到这一点,下面是一个简单的函数示例:

(define (hypot x y)
  (sqrt (+ (* x x) (* y y))))

及其 CPS 转换版本:

(define (hypot x y k)
  (* x x (lambda (x2)
           (* y y (lambda (y2)
                    (+ x2 y2 (lambda (sum)
                               (sqrt sum k))))))))

(假设*+sqrt也都经过 CPS 转换,以接受延续论点)。


所以现在,有趣的部分:CPS 转换call/cc具有以下定义:

(define (call/cc fn k)
  (fn k k))

有了CPS变换,call/cc简单易懂,易于实现。如果没有 CPS 转换,call/cc可能需要非常神奇的实现(例如,通过堆栈复制等)。

于 2012-10-03T02:33:52.870 回答