什么之间的区别eq
,eql
,equal
和equalp
,在Common Lisp的?我知道其中一些检查类型,其中一些检查所有类型,但哪个是哪个?什么时候比其他人更好用?
来自Common Lisp:Equality Predicates
(eq x y)
当且仅当x
且y
是相同的对象时才是真的.如果
eql
谓词的参数是eq
,或者它们是具有相同值的相同类型的数字,或者它们是表示相同字符的字符对象,则谓词为true .如果
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.
还有一些说明:
当没有指定测试时,大多数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.
从这里和我老师的幻灯片
eq测试它的参数(由相同的计算机内存块表示)是否是相同的符号.
例如:
(eq'A'B)NIL
(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就像是平等的,只是更高级.数字的比较是类型不敏感的.字符和字符串的比较不区分大小写.
例如:
(equp(cons'a'b)(cons'a'b))T; 同等的
现在注意区别
等于(4 4.0)NIL
equalp(4 4.0)T; 由于equalp对数字类型不敏感