3

在有关参数化的球拍指南中,有以下代码:

(define location (make-parameter "here"))

(let ([get (parameterize ([location "with a fox"])
             (lambda () (location)))])
  (get))

代码返回"here"

评估这段代码的顺序是什么?谢谢你。

4

1 回答 1

5

这是许多语言(不仅仅是 Racket)中动态范围值的常见问题。以下是评估代码时发生的情况:

  1. 参数用location值定义"here"
  2. 输入let...
  3. 输入parameterize...
  4. 参数location随值动态更新"with a fox"
  5. 计算lambda表达式以创建一个关闭的闭包location
  6. parameterized块返回——参数location恢复到它的原始值"here"
  7. 结果lambda必然get
  8. 评价let身体...
  9. 您调用(get),它会查找 的当前值location,即 ,这就是"here"结果。

如果您仔细阅读有关参数的文档,它会解释参数始终采用堆栈中最近更新的值。由于您对值的更新"with a fox"在进入let正文之前已从堆栈中弹出,因此当您实际调用get. 一个简单的解决方法是从参数复制值并让闭包关闭副本:

(define location (make-parameter "here"))

(let ([get (parameterize ([location "with a fox"])
             (let ([loc (location)])
                (lambda () loc)))])
  (get))

现在lambdacloses over loc,它应该具有预期值。

于 2013-07-28T07:30:28.800 回答