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
请看一看
(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*)