1

set!最近我在实现方案解释器时遇到了和闭包之间的冲突。

(set! var expr ) 的描述如下:( tspl )

set!不会为var建立新绑定,而是更改现有绑定的值。它首先计算expr,然后将var分配给expr的值。在更改的绑定范围内对var的任何后续引用都将评估为新值。

关于 lambda 绑定的描述是:(tspl

创建过程时,在主体内自由出现的所有变量的绑定,不包括形式参数,都与过程一起保留。随后,每当将过程应用于一系列实际参数时,形式参数就会绑定到实际参数,保留的绑定被恢复,并评估主体。

我真的不明白'自由变量'是什么意思,我的闭包实现是创建所有当前可用变量的快照并将快照存储到闭包中。每当执行闭包时,它都会按顺序执行以下工作:(代码

  1. 创建一个引用当前执行环境的父范围的本地范围(上下文)。
  2. 将快照中的所有变量存储到新创建的范围中。
  3. 将所有具有相应参数名称的实际参数存储在新范围中。
  4. 将主体评估为新范围中的列表。

我实现set!运算符的方法是:(代码

  1. 向上查找范围(沿着父引用),直到包含具有给定名称的变量的范围。
  2. 将该范围内的变量值设置为新值。

这个过程在大多数情况下似乎都有效,但是当有一个set!内部旨在修改本地范围之外的外部变量时,这变得不可能,因为set!无法真正找到 REAL 变量,而只是存储在闭包快照中的那个。

让我用代码解释一下:

(define x 3)

((lambda ()      ;; binding(snapshot) == { x: 3 }
   (set! x 4)    ;; changing the value in local scope which derived from the snapshot.
   (display x))) ;; ==> 4

(display x)      ;; ==> 3

我该如何解决这个冲突?

4

1 回答 1

3

简单的!不要使用快照。直接访问更高级别的范围。

于 2013-02-05T21:05:26.860 回答