LISP中的变量和符号有什么区别? [英] What is the difference between a variable and a symbol in LISP?
问题描述
Jörg的回答指向正确的方向。让我补充一点。
我会谈谈与Common Lisp类似的Lisp。
符号作为数据结构
符号是Lisp中真正的数据结构。您可以创建符号,您可以使用符号,可以存储符号,可以传递符号,符号可以是较大数据结构的一部分,例如符号列表。一个符号有一个名称,可以有一个值,可以有一个函数值。
所以你可以带一个符号并设置它的值。 b
(setf(symbol-value'foo)42)
通常会写(setq foo 42)
或(set'foo 42)
或(setf foo 42)
。
表示变量的符号
但!!
(defun foo(a)
(setq a 42))
或
<$ p $ ($($))
(setq a 42))
在源代码中的上述两种形式中都有符号, a
被写为符号并使用函数 READ
读取该源代码将在某个列表中返回一个符号 a
。但 setq
操作不会将 a
的符号值设置为 42
。这里 LET
和 DEFUN
引入了一个 VARIABLE a
,我们用一个符号来写。因此, SETQ
操作会将变量值设置为 42
。
因此,如果我们看一下:
<$ p $ (bq)
(setq foo 3)
(setq baz 3))
(defvar foo nil)
我们引入一个全局变量 FOO
。
栏中第一个 SETQ
设置全局变量 FOO
的符号值, 。第二个 SETQ
将局部变量 BAZ
设置为 3
。在这两种情况下,我们都使用相同的 SETQ
,我们将该变量作为符号编写,但在第一种情况下, FOO
捐献一个全局变量和那些存储值在符号值中。在第二种情况下, BAZ
表示一个局部变量以及值如何存储,我们不知道。我们所能做的就是访问变量来获得它的价值。在Common Lisp中,没有办法使用符号 BAZ
并获取局部变量值。我们无法使用符号访问局部变量绑定及其值。这是Common Lisp中局部变量的词汇绑定工作的一部分。
例如,这导致观察,即在没有记录调试信息的编译代码中,符号 BAZ
不见了。它可以是处理器中的寄存器,也可以是其他方式实现的。符号 FOO
仍然存在,因为我们将它用作全局变量。
符号 符号是一种数据类型,是Lisp中的数据结构。 变量是一个概念性的东西。全局变量基于符号。本地词汇变量不是。 在源代码中,我们使用符号为函数,类和变量编写各种名称。
有一些概念上的重叠:
(defun foo(bar)(setq bar'baz))
在上面的SOURCE代码中, defun
, foo
, bar
, setq
和 baz
都是符号。
DEFUN
是提供宏的符号。
FOO
是提供功能的符号。
SETQ
是提供特殊操作符的符号。
BAZ
是用作数据的符号。因此,在 BAZ
之前的报价。
BAR
是一个变量。在编译的代码中,不再需要它的符号。
In terms of scope? Actual implementation in memory? The syntax? For eg, if (let a 1) Is 'a' a variable or a symbol?
Jörg's answer points in the right direction. Let me add a bit to it.
I'll talk about Lisps that are similar to Common Lisp.
Symbols as a data structure
A symbol is a real data structure in Lisp. You can create symbols, you can use symbols, you can store symbols, you can pass symbols around and symbols can be part of larger data structures, for example lists of symbols. A symbol has a name, can have a value and can have a function value.
So you can take a symbol and set its value.
(setf (symbol-value 'foo) 42)
Usually one would write (setq foo 42)
, or (set 'foo 42)
or (setf foo 42)
.
Symbols in code denoting variables
But!
(defun foo (a)
(setq a 42))
or
(let ((a 10))
(setq a 42))
In both forms above in the source code there are symbols and a
is written like a symbol and using the function READ
to read that source returns a symbol a
in some list. But the setq
operation does NOT set the symbol value of a
to 42
. Here the LET
and the DEFUN
introduce a VARIABLE a
that we write with a symbol. Thus the SETQ
operation then sets the variable value to 42
.
Lexical binding
So, if we look at:
(defvar foo nil)
(defun bar (baz)
(setq foo 3)
(setq baz 3))
We introduce a global variable FOO
.
In bar the first SETQ
sets the symbol value of the global variable FOO
. The second SETQ
sets the local variable BAZ
to 3
. In both case we use the same SETQ
and we write the variable as a symbol, but in the first case the FOO
donates a global variable and those store values in the symbol value. In the second case BAZ
denotes a local variable and how the value gets stored, we don't know. All we can do is to access the variable to get its value. In Common Lisp there is no way to take a symbol BAZ
and get the local variable value. We don't have access to the local variable bindings and their values using symbols. That's a part of how lexical binding of local variables work in Common Lisp.
This leads for example to the observation, that in compiled code with no debugging information recorded, the symbol BAZ
is gone. It can be a register in your processor or implemented some other way. The symbol FOO
is still there, because we use it as a global variable.
Various uses of symbols
A symbol is a data type, a data structure in Lisp.
A variable is a conceptual thing. Global variables are based on symbols. Local lexical variables not.
In source code we write all kinds of names for functions, classes and variables using symbols.
There is some conceptual overlap:
(defun foo (bar) (setq bar 'baz))
In the above SOURCE code, defun
, foo
, bar
, setq
and baz
are all symbols.
DEFUN
is a symbol providing a macro.
FOO
is a symbol providing a function.
SETQ
is a symbol providing a special operator.
BAZ
is a symbol used as data. Thus the quote before BAZ
.
BAR
is a variable. In compiled code its symbol is no longer needed.
这篇关于LISP中的变量和符号有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!