【问题标题】:What's the difference between eq, eql, equal and equalp, in Common Lisp?Common Lisp 中的 eq、eql、equal 和 equalp 有什么区别?
【发布时间】:2010-10-07 12:58:51
【问题描述】:

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

【问题讨论】:

    标签: syntax common-lisp equality


    【解决方案1】:

    来自Common Lisp: Equality Predicates

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

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

    如果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.
    

    【讨论】:

      【解决方案2】:

      还有一些注意事项:

      • 大多数 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。

      【讨论】:

        【解决方案3】:

        来自here和我老师的幻灯片

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

        例如:

        (eq ‘A ‘B) 无
        (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除非你真的知道自己在做什么。

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

        例如:

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

        现在注意一个区别

        (eql (cons 'a 'b) (cons 'a 'b)) 无
        (等于 (cons 'a 'b) (cons 'a 'b)) T ; equal 通常适用于打印相同的东西

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

        例如:

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

        现在注意一个区别

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

        【讨论】:

          猜你喜欢
          • 2016-08-16
          • 2016-02-18
          • 2012-03-25
          • 2011-04-20
          • 2012-06-28
          • 1970-01-01
          • 2014-07-12
          • 1970-01-01
          相关资源
          最近更新 更多