Common Lisp中的动态和词法变量 [英] Dynamic and Lexical variables in Common Lisp

查看:118
本文介绍了Common Lisp中的动态和词法变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读彼得·塞贝尔(Peter Seibel)的书《 Practical Common Lisp》.

I am reading the book 'Practical Common Lisp' by Peter Seibel.

在第6章中,变量"部分 词汇变量和闭包"和动态,又称特殊变量". http://www.gigamonkeys.com/book/variables.html

In Chapter 6, "Variables" sections "Lexical Variables and Closures" and "Dynamic, a.k.a. Special, Variables". http://www.gigamonkeys.com/book/variables.html

我的问题是,这两部分中的示例都说明了(let ...)如何遮盖全局变量,而并不能真正分辨出动态变量和词法变量之间的区别.

My problem is that the examples in both sections show how (let ...) can shadow global variables and doesn't really tell the difference between the Dynamic and Lexical vars.

我了解闭包是如何工作的,但在这个示例中,我对let的了解并不特别:

I understand how closures work but I don't really get whats so special about let in this example:

(defvar *x* 10)

(defun foo ()
  (format t "Before assignment~18tX: ~d~%" *x*)
  (setf *x* (+ 1 *x*))
  (format t "After assignment~18tX: ~d~%" *x*))


(defun bar ()
  (foo)
  (let ((*x* 20)) (foo))
  (foo))


CL-USER> (foo)
Before assignment X: 10
After assignment  X: 11
NIL


CL-USER> (bar)
Before assignment X: 11
After assignment  X: 12
Before assignment X: 20
After assignment  X: 21
Before assignment X: 12
After assignment  X: 13
NIL

我觉得这里没有什么特别的事情. bar 中最外面的 foo 会使全局 x 和由 let 包围的 foo 递增在 bar 中增加阴影的 x .有什么大不了的?我不认为这应该如何解释词汇变量和动态变量之间的区别.然而,本书仍是这样的:

I feel like there is nothing special is going on here. The outer foo in bar increments the global x, and foo surrounded by let in bar increments the shadowed x. What's the big deal? I don't see how is this supposed to explain the difference between lexical and dynamic vars. Yet the book continues like this:

那么这是如何工作的? LET如何 知道当它绑定 x 时 应该创建一个动态绑定 而不是普通的词汇绑定? 它知道,因为这个名字已经 声明为special.12每个人的名字 用DEFVAR和定义的变量 DEFPARAMETER自动声明 全球特惠.

So how does this work? How does LET know that when it binds x it's supposed to create a dynamic binding rather than a normal lexical binding? It knows because the name has been declared special.12 The name of every variable defined with DEFVAR and DEFPARAMETER is automatically declared globally special.

如果 let 使用常规词法绑定" 绑定 x 会发生什么?总而言之,动态绑定和词法绑定之间有什么区别?该示例在动态绑定方面有何特别之处?

What whould happen if let would bind x using "normal lexical binding"? All in all, what are the differences between dynamic and lexical binding and how is this example special regarding dynamic binding?

推荐答案

当对变量进行词法范围时,系统将在定义的位置查找该函数.一个自由变量的值.在对变量进行动态范围调整时,系统会在调用位置查找该函数,以查找自由变量的值.默认情况下,Common Lisp中的变量都是词汇.但是,可以使用 defvar defparameter 在顶层定义动态范围的变量.

When a variable is lexically scoped, the system looks to where the function is defined to find the value for a free variable. When a variable is dynamically scoped, the system looks to where the function is called to find the value for the free variable. Variables in Common Lisp are all lexical by default; however, dynamically scoped variables can be defined at the top level using defvar or defparameter.

一个简单的示例

词法作用域(使用setq):

(setq x 3)

(defun foo () x)

(let ((x 4)) (foo)) ; returns 3

动态作用域(使用defvar):

(defvar x 3)

(defun foo () x)

(let ((x 4)) (foo)) ; returns 4

如何让变量知道是词法变量还是动态变量? 没有.另一方面,当foo去查找X的值时,它将首先查找在顶层定义的词法值.然后,它检查该变量是否应为动态变量.如果是这样,则foo会查找调用环境,在这种情况下,它将使用let使X的值变为4.

How does the let know if a variable is lexical or dynamic? It doesn't. On the other hand, when foo goes to find the value of X, it will initially find the lexical value defined at the top level. It then checks to see if the variable is supposed to be dynamic. If it is, then foo looks to the calling environment, which, in this case, uses let to overshadow the value of X to be 4.

(注意:这是一个过分的简化,但是将有助于可视化不同作用域规则之间的差异)

这篇关于Common Lisp中的动态和词法变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆