用于检查范围是词汇还是动态的程序

Sub*_*n P 5 scheme scope racket

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

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

(let ((scope 'dynamic)) 
  (test))
Run Code Online (Sandbox Code Playgroud)

但这怎么可行呢?这应该始终打印'词汇(无论范围是词汇还是动态)对吗?因为在第一个'let'的本体范围内,范围总是被定义为'词汇..如果我错了请纠正我

Chr*_*ung 6

Scheme使用词法作用域,当然代码总是返回lexical.但是,在使用动态范围的Lisp系统中,scope确实会dynamic在该(let ((scope 'dynamic)) ...)表达式中...

为了理解这一点,您必须了解如何实现动态范围.将每个变量视为具有一堆值.因此,在评估lambda表达式时,该值lexical已被推送到scope值堆栈(通过let).当let退出块,则该值被弹出.之后,第二个let块将值推dynamic送到scope值堆栈,这是您的函数所看到的.

我非常感谢Emacs Lisp手册中关于动态绑定如何在堆栈方面工作的解释.这有助于我真正理解这个概念.

  • @SubinP调用函数时不执行`define`,函数已被定义为`(lambda()scope)`. (2认同)

mol*_*ilo 6

价值test不是

(let ((scope 'lexical)) 
    (lambda () scope))
Run Code Online (Sandbox Code Playgroud)

它只是

(lambda () scope)
Run Code Online (Sandbox Code Playgroud)

当你调用它时,(test)会对函数体进行求值,它只包含

scope
Run Code Online (Sandbox Code Playgroud)

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

对于动态范围,在scope调用函数之前不会查找绑定.
那时,绑定'lexical很久就消失了 - 它只存在于定义期间test.

当你

(let ((scope 'dynamic)) 
  (test))
Run Code Online (Sandbox Code Playgroud)

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

类似的功能

(define test  
    (lambda () 
        (let ((scope 'whatever))
            scope)))
Run Code Online (Sandbox Code Playgroud)

会像你建议的那样工作 - 总是返回'whatever- 因为即使在动态设置中,绑定'whatever也会在评估期间生效scope.