Common Lisp中的动态绑定

阿肖克·坎纳(Ashok Khanna)

这个问题是Common Lisp作用域的扩展(动态vs词汇)

我已经阅读并(希望)理解了Common Lisp中的作用域和范围的概念(链接:https : //www.cs.cmu.edu/Groups/AI/html/cltl/clm/node43.html),但是我是无法理解以下三个示例。所有示例都在SBCL / Slime / Emacs中的全新Lisp会话上运行。

示例1:打印5和5

(defvar x 100)
(defun fun1 (x)
   (print x)
   (fun2))

(defun fun2 ()
   (print x))
     
(fun1 5)

示例2:打印5和100

 (defun fun1 (x)
   (print x)
   (fun2))

 (defun fun2 ()
   (print x))
    
 (defvar x 100)
 
 (fun1 5)

示例3:打印5&5&100

(defvar x 100)

(defun fun1 (x)
  (print x)
  (fun2))

(defun fun2 ()
  (print x))

(defvar x 100)
     
(fun1 5)

x

我知道为什么fun1总是打印5(由于词法范围,但是如果我错了,请更正)。我不明白的是,为什么fun2在示例1中打印5,在示例2中打印100,然后在示例3中再次打印5?

  • 示例1:x(范围不确定的变量)在fun1中设置为5 ,因此fun2访问此值。这是正确的解释吗?
  • 示例2:defvar将x设置为100 ,但是为什么在调用fun1时不将其重新设置为5 我认为绑定是在调用函数时发生的,还是在定义函数时发生的?似乎在定义fun1时x尚未绑定,因此该程序的其余部分看不到x在fun1中的绑定(在词法范围内),然后随后的defvar发生“全局”绑定函数调用中的行为x是否是由于fun1中的词法阴影产生的,而不是由于fun2中的动态阴影产生的也就是说,这里有两个x的不同实例,因为fun1首先定义了它的x,并且当时没有看到“全局” x。
  • 示例3:由于x是首先全局设置的,因此fun1和fun2都引用了x的相同实例,因此它的值在fun1期间被更新,并且在fun2期间也被应用(均为5)?此外,当我最后要求x的值时,我得到100(为什么?当fun2返回5时?)

它与Guy Steel的Common Lisp书中的以下摘录有关,但我无法理解:

“使用词法作用域的结构在每次执行时都会为每个已建立的实体有效地生成一个新名称。因此,不会发生动态阴影(尽管可能会出现词法阴影)。当涉及动态范围时,这一点尤其重要。”

以下陈述是否总是正确的(来源:https : //courses.engr.illinois.edu/cs421/sp2010/lectures/dynamicscope.pdf):

Lisp中的绑定规则是这样的:名称的使用绑定到该名称的最新声明,该声明仍然有效。

我已经开始理解其中的某些部分,但是无法对这三个部分进行全面的了解,因此,如果您能提供帮助,那将非常有帮助。

核心转储

示例1:x(范围不确定的变量)在fun1中设置为5,因此fun2访问此值。这是正确的解释吗?

通常,让我对此进行扩展。

x被宣布defvar,该变量被声明为特殊的,从现在开始x始终被视为一个特殊的变量,并动态绑定。你打电话的时候:

(fun1 5)

结合中fun1是动态的,这意味着双方的返回值fun1,并fun2基于当前动态结合x

示例2:即,这里有x的两个不同实例,因为fun1首先定义了它的x,但当时没有看到“全局” x。

是的,但并非所有的口译员都这样(请参见Sylwester的答案)。当您定义时fun1x并不特别。这意味着此时参数的范围x是词法。稍后,当defvar被求值时,xin的绑定fun1仍然是词法的,因此调用fun1不会修改全局变量的动态绑定x

示例3:[...]此外,当我要求最后的x值时,我得到100(为什么?当fun2返回5时?

特殊变量的范围不确定的,它们在任何地方都是可见的,但是它们的绑定具有动态范围,这意味着绑定的寿命只有建立它的形式。

在这里,当您x在顶层请求时,您具有全局绑定到的值x,100;值5仅x在调用有效时临时绑定fun1

如果您曾经SETF更改了绑定,则可以更改全局绑定,但是在函数应用程序或let绑定期间不会发生这种情况

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Common Lisp中的函数名称和动态绑定

来自分类Dev

Common Lisp中的条件变量绑定

来自分类Dev

Common Lisp中的动态类型规范?

来自分类Dev

在 Common Lisp 中构建动态 COND 子句

来自分类Dev

如何在Common Lisp中修改函数绑定?

来自分类Dev

Common Lisp(SBCL)中的动态变量关闭

来自分类Dev

(组成)在Common Lisp中

来自分类Dev

Common Lisp中的'()vs()

来自分类Dev

#ifndef在Common Lisp中

来自分类Dev

Common Lisp中的功能范围

来自分类Dev

更改-在Common Lisp中变为+

来自分类Dev

Common Lisp中的矩阵乘法

来自分类Dev

更改-在Common Lisp中变为+

来自分类Dev

Common Lisp中的功能范围

来自分类Dev

Common Lisp 中的变量范围

来自分类Dev

在 common lisp 中获取“common-lisp:setf common-lisp:list* 未定义”

来自分类Dev

常见Lisp中的局部动态绑定

来自分类Dev

从Common Lisp中的列表中删除项目

来自分类Dev

从Common Lisp中的列表中删除项目

来自分类Dev

如何在Common Lisp中映射功能?

来自分类Dev

在Common Lisp中调用函数列表

来自分类Dev

关于Common Lisp中的MERGE函数

来自分类Dev

为什么FEXPR被丢弃在Common Lisp中?

来自分类Dev

Common Lisp中的条件Windows注释

来自分类Dev

Common Lisp中的环境目的是什么?

来自分类Dev

在Common Lisp中创建隐藏文件

来自分类Dev

从Common Lisp中的SQLite捕获错误

来自分类Dev

在Common Lisp(CLOS)中列出对象方法

来自分类Dev

在Common Lisp REPL中更改文本的颜色