2

目前我正在阅读“Lisp 之国”。在最近的一个代码示例中,作者给出了:

> (eq 'fooo 'FoOo)
T

证明符号不区分大小写。几页后数据模式正式介绍。

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

> (eq 'Eq 'EQ)
T

伟大的。这按预期工作。但是如果我把它放到数据模式的列表中呢?请记住,我只是在尝试一些对我来说是新的东西。

> (eq '(Eq) '(EQ))
NIL
> (eq '('Eq) '('EQ))
NIL

嗯。好的?这是为什么?我原以为如果我将相同的符号放入两个列表中,那么这些列表将被视为相等。

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

4

4 回答 4

4

符号区分大小写

> (eq (print (intern "foo")) (print (intern "FOO")))
|foo|   ; printed 
FOO     ; printed
==> NIL ; returned

默认阅读器是大小写转换

(eq (read-from-string "foo") (read-from-string "FOO"))
==> T

但是,您可以让读者保持大小写:

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

请看一下

EQ 比较指针标识

Common Lisp 提供了4 个相等谓词,您应该根据需要使用正确的一个:

(equal '(Eq) '(EQ))
==> T
(equal '('Eq) '('EQ))
==> T
于 2013-12-02T03:43:53.913 回答
2

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

这里的解决方案是使用equalwhich 只是做“智能”的事情并比较列表的元素

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

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

于 2013-12-02T03:47:08.353 回答
1

Lisp 符号区分大小写。甚至 lisp 阅读器也区分大小写。唯一的一点是,当读者阅读一个符号时,它通常是大写的。告诉读者重要的案例的最简单方法是将其放在垂直线之间。

> '|asd|def|ghj|
|asdDEFght|
> '|asd|
|asd|
> '|ASD|
ASD
> 'ASD
ASD
> (eq 'asd '|ASD|)
t
> (eq 'asd '|aSd|)
nil

谓词检查参数是否是相同的eq对象(类似于比较指向变量的指针C

> (defparameter *x* 1)
> (defparameter *y* 1)
> (eq *x* *y*)
nil

'(asd)因此,当您在列表中写入REPL一个元素时,就会创建。当您第二次编写它时,会创建另一个列表,这些列表实际上是不同的对象。

> (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以查看差异。

于 2013-12-02T05:24:02.593 回答
1

使事情复杂一点。

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

(defparameter *a* '(1))
(defparameter *b* '(1))

现在我们计算:

(eq *a* *b*)

如果 this 是NIL或,它是未定义的T。Common Lisp 编译器可能会检测到这些列表equal,并将两个变量设置为同一个列表 - 这EQ也是如此。实际上有 Common Lisp 编译器正在这样做。DEFPARAMETER在 *REPL one would usually expect that the Lisp system does not detect that and that(eq a *b*) isNIL`中执行这两种形式。

EQUAL比较结构,(eq *a* *b*)对于我们的示例来说,总是T.

于 2013-12-02T09:38:04.487 回答