以下表达式中的当前延续是什么?

时间:2012-10-03 02:16:09

标签: scheme continuations

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

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

任何人都可以详细解释当前的延续吗?

2 个答案:

答案 0 :(得分:2)

(k 12)之类的东西不是延续。在一些较大的程序中,每个子表达都有一个延续。例如,x(* 3 (+ x 42))的延续为(lambda (_) (* 3 (+ _ 42)))

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

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

答案 1 :(得分:1)

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

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

具有相同的结果
(display 12)

Scheme中的延续“外观和感觉”就像程序一样,但它们实际上并不像程序那样。有助于您更好地理解延续的一件事是CPS转换。


在CPS转换中,而不是返回值的函数,而是采用continuation参数,并使用结果调用continuation。因此,CPS转换的sqrt函数将使用(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可能需要一个非常神奇的实现(例如,通过堆栈复制等)。