82

Common Lisp 中的 ,​​ 和 ,eq有什么eql区别?我知道他们中的一些检查类型,其中一些检查类型以及所有这些,但是哪个是哪个?什么时候比其他更好用?equalequalp

4

3 回答 3

87

来自Common Lisp:等式谓词

(eq x y)当且仅当xy是同一个相同对象时为真。

如果它的eql参数是eq,或者如果它们是具有相同值的相同类型的数字,或者如果它们是表示相同字符的字符对象,则谓词为真。

如果equal谓词的参数是结构相似(同构)的对象,则谓词为真。一个粗略的经验法则是,当且仅当它们的打印表示相同时,两个对象才相等。

两个对象equalp是否相等;如果它们是字符并且满足 char-equal,则忽略字母大小写和字符的某些其他属性;如果它们是数字并且具有相同的数值,即使它们是不同的类型;或者如果他们的组件都是equalp.

以下是我在上面链接到的同一页面中的一些示例:

(eq 'a 'b) is false. 
(eq 'a 'a) is true. 
(eq 3 3) might be true or false, depending on the implementation. 
(eq 3 3.0) is false. 
(eq 3.0 3.0) might be true or false, depending on the implementation. 
(eq #c(3 -4) #c(3 -4)) 
  might be true or false, depending on the implementation. 
(eq #c(3 -4.0) #c(3 -4)) is false. 
(eq (cons 'a 'b) (cons 'a 'c)) is false. 
(eq (cons 'a 'b) (cons 'a 'b)) is false. 
(eq '(a . b) '(a . b)) might be true or false. 
(progn (setq x (cons 'a 'b)) (eq x x)) is true. 
(progn (setq x '(a . b)) (eq x x)) is true. 
(eq #\A #\A) might be true or false, depending on the implementation. 
(eq "Foo" "Foo") might be true or false. 
(eq "Foo" (copy-seq "Foo")) is false. 
(eq "FOO" "foo") is false.


(eql 'a 'b) is false. 
(eql 'a 'a) is true. 
(eql 3 3) is true. 
(eql 3 3.0) is false. 
(eql 3.0 3.0) is true. 
(eql #c(3 -4) #c(3 -4)) is true. 
(eql #c(3 -4.0) #c(3 -4)) is false. 
(eql (cons 'a 'b) (cons 'a 'c)) is false. 
(eql (cons 'a 'b) (cons 'a 'b)) is false. 
(eql '(a . b) '(a . b)) might be true or false. 
(progn (setq x (cons 'a 'b)) (eql x x)) is true. 
(progn (setq x '(a . b)) (eql x x)) is true. 
(eql #\A #\A) is true. 
(eql "Foo" "Foo") might be true or false. 
(eql "Foo" (copy-seq "Foo")) is false. 
(eql "FOO" "foo") is false.


(equal 'a 'b) is false. 
(equal 'a 'a) is true. 
(equal 3 3) is true. 
(equal 3 3.0) is false. 
(equal 3.0 3.0) is true. 
(equal #c(3 -4) #c(3 -4)) is true. 
(equal #c(3 -4.0) #c(3 -4)) is false. 
(equal (cons 'a 'b) (cons 'a 'c)) is false. 
(equal (cons 'a 'b) (cons 'a 'b)) is true. 
(equal '(a . b) '(a . b)) is true. 
(progn (setq x (cons 'a 'b)) (equal x x)) is true. 
(progn (setq x '(a . b)) (equal x x)) is true. 
(equal #\A #\A) is true. 
(equal "Foo" "Foo") is true. 
(equal "Foo" (copy-seq "Foo")) is true. 
(equal "FOO" "foo") is false.


(equalp 'a 'b) is false. 
(equalp 'a 'a) is true. 
(equalp 3 3) is true. 
(equalp 3 3.0) is true. 
(equalp 3.0 3.0) is true. 
(equalp #c(3 -4) #c(3 -4)) is true. 
(equalp #c(3 -4.0) #c(3 -4)) is true. 
(equalp (cons 'a 'b) (cons 'a 'c)) is false. 
(equalp (cons 'a 'b) (cons 'a 'b)) is true. 
(equalp '(a . b) '(a . b)) is true. 
(progn (setq x (cons 'a 'b)) (equalp x x)) is true. 
(progn (setq x '(a . b)) (equalp x x)) is true. 
(equalp #\A #\A) is true. 
(equalp "Foo" "Foo") is true. 
(equalp "Foo" (copy-seq "Foo")) is true. 
(equalp "FOO" "foo") is true.
于 2009-02-13T20:00:36.930 回答
29

还有一些注意事项:

  • 大多数 CL 函数在未指定测试时隐式使用 EQL

  • 另请参见 STRING-EQUAL、= 和 TREE-EQUAL

  • EQ的核心通常是指针比较

和一个粗略的指南:

比较...使用...

对象/结构均衡器

NIL EQ(但函数 NULL 更简洁,可能更便宜)

T EQ(或者只是值,但你不关心类型)

精确数字 EQL

浮动 =

字符 EQL 或 CHAR-EQUAL

Lists, Conses, Sequences EQ(如果你想要完全相同的对象)
                           EQUAL(如果你只关心元素)

字符串 EQUAL(区分大小写)、EQUALP(不区分大小写)
                           STRING-EQUAL(如果您将符号混入其中)

树(列表的列表) TREE-EQUAL(带有适当的 :TEST 参数)

请注意,为了提高效率,通常使用 EQ >> EQL >> EQUAL >> EQUALP。

于 2009-02-14T08:43:21.433 回答
11

这里和我老师的幻灯片

eq测试它的参数(由同一块计算机内存表示)是否是相同的符号。

例如:

(eq 'A 'B) NIL
(eq 'RAM 'RAM) T
(eq (cons 'a 'b) (cons a' b')) ; 这是因为对两个 cons 进行了不同的调用,因此显然会为它们分配不同的内存块

eql首先测试它的参数是否满足 EQ,如果不满足,它会尝试查看它们是否是相同类型和值的数字。

例如:

(eql 4 4.0) 无
(eql 4 4) T

现在注意一个区别

(eq 4.0 4.0) NIL ; 取决于平台,如第一个(接受的)答案中所述
(eql 4.0 4.0) T ; 参数的类型和值相同

在某些实现上(eq 4.0 4.0)可能会返回 true,因为标准中没有指定实现是否应该只在内存中保留一份数字和字符的副本,就像使用符号一样)。根据经验 ,不要使用eq on numbers and characters除非你真的知道你在做什么。

equal是一个“更健全”的比较函数。根据经验,您可以将其视为告诉您两个对象是否看起来相同(结构相似或同构)。它可能是您要用于一般相等的运算符。对于数字、字符和符号,它的行为类似于 eql,但对于列表(conses)和字符串,它告诉它们的元素是否

例如:

(等于 4 4) T
(等于 (+ 2 2) 4) T

现在注意一个区别

(eql (cons 'a 'b) (cons 'a 'b)) NIL
(equal (cons 'a 'b) (cons 'a 'b)) T ; equal 通常对于打印相同的东西是正确的

equalp就像相等,只是更高级。数字比较是类型不敏感的。字符和字符串的比较不区分大小写。

例如:

(equalp (cons 'a 'b) (cons 'a 'b)) T ; 等于等于

现在注意一个区别

等于(4 4.0)零等于(4
4.0)T;由于 equalp 对数字类型不敏感

于 2014-02-15T10:18:42.807 回答