【问题标题】:Which is the current continuation in the following expression?以下表达式中的当前延续是哪个?
【发布时间】:2012-10-03 02:16:08
【问题描述】:

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

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

谁能详细解释一下当前的延续是什么?

【问题讨论】:

    标签: scheme continuations


    【解决方案1】:

    (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)))

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

    【讨论】:

      【解决方案2】:

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

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

      结果与

      相同
      (display 12)
      

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


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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-09
        • 1970-01-01
        • 2015-02-11
        • 2019-03-15
        • 2021-07-18
        • 2016-04-13
        • 2016-11-27
        • 1970-01-01
        相关资源
        最近更新 更多