defvar、defparameter、setf 和 setq 之间有什么区别
我发现了一个类似问题。
但我不太明白这个解释。
所以我尝试使用以下示例运行 clisp:
[1]> (defvar a 5)
A
[2]> (+ a 1)
6
[3]> (defparameter b 5)
B
[4]> (+ b 1)
6
[5]> (setf c 5)
5
[6]> (+ c 1)
6
[7]> (setq d 5)
5
[8]> (+ d 1)
6
[9]> (let ((a 500)) (+ a 1))
501
[10]> (let ((b 500)) (+ b 1))
501
[11]> (let ((c 500)) (+ c 1))
501
[12]> (let ((d 500)) (+ d 1))
501
[13]>
我发现的是完全相同的。
我不明白他们有什么不同?
I found a Similar question.
But I don't quite understand that explanation.
So I'm trying to run clisp with the following example:
[1]> (defvar a 5)
A
[2]> (+ a 1)
6
[3]> (defparameter b 5)
B
[4]> (+ b 1)
6
[5]> (setf c 5)
5
[6]> (+ c 1)
6
[7]> (setq d 5)
5
[8]> (+ d 1)
6
[9]> (let ((a 500)) (+ a 1))
501
[10]> (let ((b 500)) (+ b 1))
501
[11]> (let ((c 500)) (+ c 1))
501
[12]> (let ((d 500)) (+ d 1))
501
[13]>
What I found is totally the same.
I can't figure out what's different with them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
defvar
和defparameter
都将变量声明为“动态作用域变量”。此外,defparameter 始终将变量的值设置为您作为第二个参数传入的值。这与defvar
不同,它只会设置之前未设置的变量值。在全局词法作用域中使用
setf
或setq
定义变量是未定义的。有些实现将为您创建动态范围的变量,有些则不会。第一次执行此操作时,您可能会看到诊断消息。要了解词法作用域变量和动态作用域变量之间的区别,请尝试以下代码片段:
这里我们创建一个动态作用域变量和一个返回值的函数(在绑定内部定义,在函数创建期间它具有不同的值) ,这不是必需的,这样做只是为了看起来类似于 b) 上的词法闭包。然后我们定义一个新变量并定义一个返回其值的函数。
之后,我们调用这两个函数,在闭包内将一个值绑定到同名的变量。在动态作用域的情况下,它是相同的变量。在词法闭包情况 (b) 中,它们仅具有相同的名称,但不是相同的变量,因为它们是在两个不同的词法闭包中定义的。
至于
setf
和setq
之间的区别,请尝试始终使用setf
(我想不出任何(setq blah blahblah)
可以工作,而(setf blah blahblah)
不会做同样的事情)。Both
defvar
anddefparameter
will declare a variable as a "dynamically scoped variable". In addition,defparameter
will always set the value of the variable to the value you pass in as the second argument. This is different fromdefvar
, it will only set the value of the variable if it previously hasn't been set.Defining a variable with
setf
orsetq
in the global lexical scope is undefined. Some implementations will create a dynamically scoped variable for you, some will not. You may see diagnostic messages when you do it for the first time.To understand the difference between lexically-scoped and dynamically-scoped variables, try the following code snippet:
Here we create a dynamically-scoped variable and a function that return the value (defined inside a binding where it has a different value during the function creation, this is not necessary and done only to look similar to the lexical closure over b). We then define a new variable and define a function return its value.
After that, we call both functions, inside closures binding a value to a variable of the same name. In the dynamic scoping case, it is the same variable. In the lexical closure case (b), they merely have the same name, but are not the same variable, since they're defined in two different lexical closures.
As far as the difference between
setf
andsetq
, try to always usesetf
(I cannot think of any example where(setq blah blahblah)
would work and(setf blah blahblah)
wouldn't do the same thing).DEFPARAMETER
始终分配一个值。所以:虽然
DEFVAR
只执行一次,所以:SETF
是一个内部使用SETQ
的宏,但有更多的可能性。在某种程度上,它是一个更通用的赋值运算符。例如,使用SETF
可以做到这一点:但使用
SETQ
则不能这样做:DEFPARAMETER
always assigns a value. So:while
DEFVAR
does it only once, so:SETF
is a macro which usesSETQ
internally, but has more possibilities. In a way it's a more general assignment operator. E.g. withSETF
you can do:but you can't do that with
SETQ
: