Common lisp 理解Lisp中的数据模式,为什么这些表达式不一样?

Common lisp 理解Lisp中的数据模式,为什么这些表达式不一样?,common-lisp,equality,land-of-lisp,Common Lisp,Equality,Land Of Lisp,目前我正在读《口齿不清的土地》。在作者最近的一个代码示例中: > (eq 'fooo 'FoOo) T 证明符号不区分大小写。几页之后,正式引入了数据模式 然而,我无法真正理解以下内容eq是一个函数,因此其名称也不区分大小写。因此,我应该能够做到这一点: > (eq 'Eq 'EQ) T 太好了。这是意料之中的事。但是如果我把它放在数据模式的列表中呢?记住,我只是在尝试一些对我来说是新的东西 > (eq '(Eq) '(EQ)) NIL > (eq '('Eq) '(

目前我正在读《口齿不清的土地》。在作者最近的一个代码示例中:

> (eq 'fooo 'FoOo)
T
证明符号不区分大小写。几页之后,正式引入了数据模式

然而,我无法真正理解以下内容
eq
是一个函数,因此其名称也不区分大小写。因此,我应该能够做到这一点:

> (eq 'Eq 'EQ)
T
太好了。这是意料之中的事。但是如果我把它放在数据模式的列表中呢?记住,我只是在尝试一些对我来说是新的东西

> (eq '(Eq) '(EQ))
NIL
> (eq '('Eq) '('EQ))
NIL
嗯。可以为什么呢?如果我把同一个符号放在两个列表中,我会认为这两个列表是相等的

现在的问题是:这是否意味着不是比较列表的内容,而是比较列表的“对象”本身?我遗漏了什么?

符号区分大小写 默认读取器是大小写转换 但是,您可以使读卡器保持大小写:

(let ((*readtable* (copy-readtable)))
  (setf (readtable-case *readtable*) :preserve)
  (eq (read-from-string "foo") (read-from-string "FOO")))
==> NIL
请看一看

EQ比较指针标识 ,您应该根据自己的需要使用合适的:

(equal '(Eq) '(EQ))
==> T
(equal '('Eq) '('EQ))
==> T

eq
比较事物是否完全相同,认为指针相等。这就像Java中的
==
,即使逻辑上等价的数据也会出错

这里的解决方案是使用
equal
,它只执行“智能”操作并比较列表的元素

> (equal '(A) '(a))
T

此外,符号区分大小写。但是默认情况下,阅读器(将代码转换为AST的东西)默认不区分大小写。您可以通过类似于
intern

的函数注意到这种区别,Lisp符号区分大小写。甚至lisp阅读器也是区分大小写的。唯一的一点是,当读者阅读一个符号时,它通常是大写的。告诉读者这个案例很重要的最简单的方法就是把它放在垂直线之间

> '|asd|def|ghj|
|asdDEFght|
> '|asd|
|asd|
> '|ASD|
ASD
> 'ASD
ASD
> (eq 'asd '|ASD|)
t
> (eq 'asd '|aSd|)
nil
eq
谓词检查参数是否是相同的对象(类似于比较
C
中变量的指针)

因此,当您在
REPL
中写入
”(asd)
时,将创建包含一个元素的列表。当你第二次写的时候,另一个列表被创建了,这些列表实际上是不同的对象

> (defparameter *list1* '('qwe))
> (defparameter *list2* '('qwe))
> (eq *list1* list2*) ;this are 2 different objects
nil
> (setf (first *list1* 'def))
> *list1* ;this list has changed
(DEF)
> *list2* ;and this did not
(QWE)

> (setf *list1* *list2*) ;now they are just different names for one object
> *list1*
(QWE)
> (eq *list1* *list2*)
t

还有其他方法可以比较对象(
eq
eql
equal
equalp
=
)。最好阅读文档并使用
REPL
查看差异。

将事情复杂化一点

假设我们在一个文件中有以下内容。然后我们编译并加载该文件

(defparameter *a* '(1))
(defparameter *b* '(1))
现在我们计算:

(eq *a* *b*)
如果这是
NIL
T
,则它是未定义的。公共Lisp编译器可能会检测到列表是
相等的
,并将这两个变量设置为相同的列表-即
EQ
,然后也会是真的。实际上,有一些常见的Lisp编译器正在这样做。在*REPL
中执行两个
DEFPARAMETER
表单时,人们通常会认为Lisp系统没有检测到这一点,并且
(eq a*b*)
NIL`


EQUAL
比较结构和
(eq*a**b*)
因为我们的例子总是
T

哎哟,我感觉我没有太多窥视表面后面的东西。谢谢你的详细帮助!
> (defparameter *list1* '('qwe))
> (defparameter *list2* '('qwe))
> (eq *list1* list2*) ;this are 2 different objects
nil
> (setf (first *list1* 'def))
> *list1* ;this list has changed
(DEF)
> *list2* ;and this did not
(QWE)

> (setf *list1* *list2*) ;now they are just different names for one object
> *list1*
(QWE)
> (eq *list1* *list2*)
t
(defparameter *a* '(1))
(defparameter *b* '(1))
(eq *a* *b*)