关于Racket中“参数化”和“让”的评估顺序是什么?

时间:2013-07-28 07:07:53

标签: lisp scheme racket evaluation let

在关于parameterize的“球拍指南”中,有以下代码:

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

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

代码返回"here"

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

1 个答案:

答案 0 :(得分:5)

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

  1. location参数定义为值"here"
  2. 输入let ...
  3. 输入parameterize ...
  4. 参数location使用值"with a fox"
  5. 动态更新
  6. 评估lambda表达式以创建一个关闭location
  7. 的闭包
  8. parameterized阻止参数location返回原始值"here"
  9. 生成的lambda绑定到get
  10. 评估let正文......
  11. 您致电(get),它会查找location的当前值,即"here",这就是结果。
  12. 如果仔细阅读有关参数的文档,则说明参数始终采用堆栈中最接近更新的值。由于您的值"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,它应具有预期值。