Common Lisp中的eq,eql,equal和equalp有什么区别?

时间:2009-02-13 19:56:16

标签: syntax common-lisp equality

Common Lisp中eqeqlequalequalp之间的区别是什么?我知道其中一些检查类型,其中一些检查所有类型,但哪个是哪个?什么时候比其他人更好用?

3 个答案:

答案 0 :(得分:75)

来自Common Lisp: Equality Predicates

  当且仅当(eq x y)x是相同的对象时,

y才为真。

     

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

     

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

     

如果它们相等,则两个对象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.

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

{{1}}

答案 1 :(得分:28)

更多说明:

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

  • 另见STRING-EQUAL,=和TREE-EQUAL

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

粗略指南:

To compare against...      Use...

Objects/Structs            EQ

NIL                        EQ (but the function NULL is more concise and probably cheaper)

T                          EQ (or just the value but then you don't care for the type)

Precise numbers            EQL

Floats                     =

Characters                 EQL or CHAR-EQUAL

Lists, Conses, Sequences   EQ (if you want the exact same object)
                           EQUAL (if you just care about elements)

Strings                    EQUAL (case-sensitive), EQUALP (case-insensitive)
                           STRING-EQUAL (if you throw symbols into the mix)

Trees (lists of lists)     TREE-EQUAL (with appropriate :TEST argument)

注意,效率通常为EQ>> EQL>> EQUAL>> EQUALP。

答案 2 :(得分:11)

来自here和我老师的幻灯片

  

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

例如:

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

  

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

例如:

(eql 4 4.0)NIL
(eql 4 4)T

现在注意差异

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

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

  

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

例如:

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

现在注意差异

(eql(cons'a'b)(cons'a'b))NIL
(等于(cons'a'b)(cons'a'b))T; 相同通常适用于打印相同

的内容
  

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

例如:

(equalp(cons'a'b)(cons'a'b))T; 与平等相同

现在注意差异

相等(4 4.0)无 equalp(4 4.0)T; 由于equalp对数字类型不敏感地处理