Racket中关于“parameterize”和“let”的评估顺序是什么?

3

在Racket指南关于parameterize的部分中,有以下代码:

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

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

这段代码返回"here"

这段代码的求值顺序是什么?谢谢。

1个回答

5
这是许多语言(不仅仅是Racket)中动态作用域值的常见问题。以下是代码评估时发生的情况:
  1. 使用值"here"定义参数location
  2. 进入let...
  3. 进入parameterize...
  4. 参数location被动态更新为值"with a fox"
  5. lambda表达式进行求值以创建一个闭包,该闭包封闭了location
  6. parameterized块返回-参数location恢复到其原始值"here"
  7. 将生成的lambda绑定到get
  8. 评估let主体...
  9. 调用(get),它查找当前值为"here"location,这就是结果。
如果仔细阅读有关参数的文档,它会解释参数始终采用堆栈中最近更新的值。由于使用值"with a fox"的更新在进入let主体之前从堆栈中弹出,因此在实际调用get时不再可见。一个简单的解决方法是复制参数的值并让闭包封闭副本。
(define location (make-parameter "here"))

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

现在,lambda 闭合于 loc,这应该是期望的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接