【问题标题】:Environment not part of a continuation?环境不是延续的一部分?
【发布时间】:2011-05-14 10:16:59
【问题描述】:

环境不是方案延续的一部分吗?

我用 Chicken、Gauche、Racket 和 Gambit 对此进行了测试,它们的行为都相似:

(define kont #f)

(let ((a 1)
      (b 2))
  (call-with-current-continuation
   (lambda (k)
     (set! kont k)
     (display 'mutating)
     (newline)
     (set! a -1)
     (set! b -2)))
  (display (+ a b))
  (newline))

我希望在评估 LET 时为 -3,但在对 kont 的调用中为 +3(因为我认为程序会在突变之前记住 a 和 b 的绑定):

(let ... ) ; <-- evaluating the LET above
; prints "mutating"
=> -3
(kont 100)
=> -3
(kont 100)
=> -3

所以延续只影响控制,而不影响环境?在这种情况下,为什么说实现延续的方法之一是“复制堆栈”(绑定不在堆栈上?)

【问题讨论】:

  • 或者是延续携带环境和绑定,但是这些可变的?

标签: scheme continuations


【解决方案1】:

延续捕获绑定。但是,正如您所猜测的那样,这些绑定是可变的。

在这里,您被“复制堆栈”的口号误导了。虽然这是考虑 call/cc 的合理方式,但这并不是故事的全部。一方面,您真的不希望公开本地绑定是否为堆栈分配的语言功能。

相反,call/cc 是使用“程序上下文”的概念定义的。为了更好地解决这个问题,您可能想看看 Shriram Krishnamurthi 的(免费,在线)教科书PLAI,或(不是免费的,更深入的)书“Semantics Engineering with PLT Redex”。

顺便说一句;您的程序并没有真正检查您希望它检查的内容,因为您从未调用过捕获的延续。我想你想写这样的东西:

#lang racket

(define kont #f)

(let ([a 3])

  (let/cc k
    (set! kont k)
    (set! a 4))
  (printf "~s\n" a))

(kont)

...这显示了您上面提到的几乎相同的行为。

【讨论】:

    【解决方案2】:

    您可以使用 set! 在环境中更改 a 和 b 的值。所以 a 和 b 在 continuation 环境中是 -1 和 -2。您无法展开副作用。在你的延续中,a、b 和 kont 之间没有区别。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-12
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      相关资源
      最近更新 更多