环境不是计划延续的一部分吗?
我用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))
我希望-3在评估LET时,但在调用kont时为+3(因为我认为程序会记住突变前a和b的绑定):
(let ... ) ; <-- evaluating the LET above
; prints "mutating"
=> -3
(kont 100)
=> -3
(kont 100)
=> -3
所以延续只影响控制,而不影响环境?在这种情况下,为什么说实现continuation的方法之一是“复制堆栈”(绑定不在堆栈上?)
答案 0 :(得分:3)
延续捕获绑定。但是,正如你猜测的那样,这些绑定是可变的。
你在这里被“复制堆栈”的口号误导了。虽然这是考虑呼叫/ cc的合理方式,但并不是整个故事。首先,你真的不想要一个暴露本地绑定是否是堆栈分配的语言功能。
相反,call / cc是使用“program contexts”的概念定义的。要想对此有所了解,您可能需要查看Shriram Krishnamurthi(免费在线)教科书PLAI,或者(非免费,更深入)的书“使用PLT Redex的语义工程” ”。
撇开;你的程序并没有真正检查你想要检查的内容,因为你从未调用过捕获的延续。我想你想写这样的东西:
#lang racket
(define kont #f)
(let ([a 3])
(let/cc k
(set! kont k)
(set! a 4))
(printf "~s\n" a))
(kont)
...显示了与上面提到的几乎相同的行为。
答案 1 :(得分:1)
您可以使用set!更改环境中a和b的值。所以a和b在连续环境中是-1和-2。您无法展开副作用。在你的继续中,a,b和kont之间没有区别。