解释延续中引用的变量的不同行为? [英] Explaining different behavior of variables referenced in continuations?

查看:75
本文介绍了解释延续中引用的变量的不同行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是两种情况,它们在调用存储的延续时对 i 的值具有不同的行为.如何解释这种差异?

Following are two case which have different behaviors regarding the value of i across calls to stored continuations. How can the difference be explained?

>(define cc #f)
>(define (x)
    (let ((i 0))
    (set! i (+ i 100))
    (+ i (+ i (call/cc (lambda (k) (set! cc k) 1)))) ; call/cc is not included by set!
    (set! i (+ i 10))
    i))
> (x)
110
> (cc 50) ; the context variable i changes as cc calling
120
> (cc 50)
130

案例 B

> (define cc #f)
> (define (x)
    (let ((i 0))
    (set! i (+ i 100))
    (set! i (+ i (call/cc (lambda (k) (set! cc k) 1)))) ; call/cc is included by set!
    (set! i (+ i 10))
    i))
> (x)
111
> (cc 50) ; the context variable i always be 0, not changing as cc calling
160
> (cc 50)
160        

推荐答案

我在这里做假设,所以如果我错了,请原谅我 :)

I'm making assumptions here, so forgive me if I'm wrong :)

我能够在 Racket 和我的宠物 Scheme 实现中重现这一点.问题可能隐藏在特定 Scheme 实现中延续的实现方式中.所以这是我的假设:

I was able to reproduce this in Racket and in my pet Scheme implementation. The problem may hide in the way the continuations are implemented in the specific Scheme implementation. So here are my assumptions:

  • 实现从左到右评估过程的参数.
  • 结果值存储在堆栈中.
  • 调用 call/cc 时会复制堆栈,并且该副本包含评估的过程参数.
  • 当延续被调用时,复制的堆栈与评估的过程参数一起恢复.
  • The implementation evaluates the arguments of a procedure from left to right.
  • The resulting values are stored in a stack.
  • The stack is copied when calling call/cc and the copy contains the evaluated procedure arguments.
  • When the continuation is called the copied stack is restored together with the evaluated procedure arguments.

这意味着在

(set! i (+ i (call/cc (lambda (k) (set! cc k) 1))))

+ 应用程序中的

icall/cc 之前被评估,它的值 100 存储在堆.当 cc 被调用时,它不会重新计算 i 而是使用之前计算过的值 100.所以当调用 (cc 50) 你得到

i in the + application is evaluated before call/cc and its value 100 is stored in the stack. When cc is called it does not reevaluate i and instead uses the value 100, evaluated before. So when calling (cc 50) you get

(set! i (+ 100 50))

如果切换call/cci的位置,则i会被重新评估,从而得到正确的结果.>

If you switch the places of call/cc and i, then i will be reevaluated and thus you get correct results.

(define cc #f)
(define (x)
    (let ((i 0))
    (set! i (+ i 100))
    (set! i (+ (call/cc (lambda (k) (set! cc k) 1)) i))
    (set! i (+ i 10))
    i))
> (x)
111
> (cc 50)
171
> (cc 50)
231

这篇关于解释延续中引用的变量的不同行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆