【问题标题】:Program to check if the scoping is lexical or dynamic检查范围是词法还是动态的程序
【发布时间】:2015-11-27 10:59:04
【问题描述】:

我发现检查范围是词法还是动态的程序是下面给出的程序(来源:http://inst.eecs.berkeley.edu/~cs61a/su10/resources/sp11-Jordy/scope/)

(define test 
  (let ((scope 'lexical)) 
    (lambda () scope)))

(let ((scope 'dynamic)) 
  (test))

但是这怎么可能呢?这应该总是打印 'lexical (不管范围是词法还是动态)对吗?因为在第一个'let'主体的本地范围内,范围总是被定义为'词法..如果我错了请纠正我

【问题讨论】:

    标签: scope scheme racket


    【解决方案1】:

    方案使用词法作用域,所以当然该代码总是返回lexical。然而,在使用动态作用域的 Lisp 系统中,scope 确实是 dynamic 在 (let ((scope 'dynamic)) ...) 表达式中......。

    为了理解这一点,您必须了解动态范围是如何实现的。将每个变量想象成一个堆栈值。† 因此,当计算 lambda 表达式时,值 lexical 已被推送到 scope 的值堆栈(通过 @987654328 @)。当let 块退出时,该值被弹出。稍后,第二个 let 块将值 dynamic 推送到 scope 的值堆栈,这是您的函数随后看到的。

    † 我非常感谢the explanation from the Emacs Lisp manual 关于动态绑定如何在堆栈方面工作。它帮助我真正理解了具体的概念。

    【讨论】:

    • 我理解了链接中的程序和这里解释的堆栈概念。谢谢你的信息。但是当从第二个'let'调用测试函数时,define块内的代码被执行,并且测试函数内的let块应该在lambda块执行之前再次将值'lexical压入堆栈,对吧? ..或者我对执行的理解有什么问题?
    • @SubinP 调用函数时define没有被执行,函数已经定义为(lambda () scope)。
    【解决方案2】:

    test的值不是

    (let ((scope 'lexical)) 
        (lambda () scope))
    

    只是

    (lambda () scope)
    

    当你调用它时,(test),函数体被评估,它只包含

    scope
    

    对于词法范围,这将是在评估定义时有效的绑定中的值,即词法封闭的let-binding。

    使用动态范围,在调用函数之前不会查找 scope 的绑定。
    那时,与'lexical 的绑定早已不复存在——它只存在于test 的定义期间。

    当你

    (let ((scope 'dynamic)) 
      (test))
    

    在环境中引入了一个新的绑定,这是查找scope时找到的绑定。

    类似功能

    (define test  
        (lambda () 
            (let ((scope 'whatever))
                scope)))
    

    将按照您建议的方式工作 - 始终返回 'whatever - 因为与 'whatever 的绑定在 scope 的评估期间有效,即使在动态设置中也是如此。

    【讨论】:

      猜你喜欢
      • 2021-12-20
      • 1970-01-01
      • 2013-05-16
      • 2022-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多