【问题标题】:What’s the sequence of evaluation concerning `parameterize' and `let' in Racket?在 Racket 中,关于“参数化”和“让”的评估顺序是什么?
【发布时间】:2013-07-28 04:04:18
【问题描述】:
在关于parameterize 的球拍指南中,有以下代码:
(define location (make-parameter "here"))
(let ([get (parameterize ([location "with a fox"])
(lambda () (location)))])
(get))
代码返回"here"。
评估这段代码的顺序是什么?谢谢。
【问题讨论】:
标签:
lisp
scheme
racket
evaluation
let
【解决方案1】:
这是许多语言(不仅仅是 Racket)中动态范围值的常见问题。评估代码时会发生以下情况:
-
location 参数定义为值"here"
- 输入
let...
- 输入
parameterize...
- 参数
location动态更新为"with a fox"
-
lambda 表达式被求值以创建一个关闭 location 的闭包
- 从
parameterized 块返回—参数location 恢复到其原始值"here"
- 生成的
lambda 绑定到get
- 评估
let body...
- 你调用
(get),它会查找location的当前值,即"here",这就是结果。
如果您仔细阅读有关参数的文档,它会解释参数始终采用堆栈中最近更新的值。由于您在进入let 主体之前使用值"with a fox" 进行的更新从堆栈中弹出,因此当您实际调用get 时它不再可见。一个简单的解决方法是从参数中复制值并让闭包关闭副本:
(define location (make-parameter "here"))
(let ([get (parameterize ([location "with a fox"])
(let ([loc (location)])
(lambda () loc)))])
(get))
现在lambda 关闭loc,它应该具有预期值。