Jaka jest różnica między eq, eql, equal i equalp w Common Lispie?

Jaka jest różnica między eq, eql, equal i equalp, W Common Lispie? Rozumiem, że niektóre z nich sprawdzają typy, niektóre sprawdzają różne typy i to wszystko, ale które jest które? Kiedy lepiej używać jednego niż drugiego?

Author: nbro, 2009-02-13

3 answers

From Common Lisp: Equality Predicates

(eq x y) jest prawdą wtedy i tylko wtedy, gdy x i y są tym samym identycznym obiektem.

Predykat eql jest prawdziwy, jeśli jego argumenty są eq, lub jeśli są liczbami tego samego typu o tej samej wartości, lub jeśli są obiektami znakowymi, które reprezentują ten sam znak.

Predykat equal jest prawdziwy, jeśli jego argumenty są obiektami strukturalnie podobnymi (izomorficznymi). Ogólną zasadą jest, że dwa obiekty są równe wtedy i tylko wtedy, gdy ich wydrukowane reprezentacje są takie same.

Dwa obiekty są equalp, jeśli są równe; jeśli są znakami i spełniają znak-equal, który ignoruje litery i pewne inne atrybuty znaków; jeśli są liczbami i mają tę samą wartość liczbową, nawet jeśli są różnych typów; lub jeśli mają składniki, które są wszystkie equalp.

Oto kilka przykładów z tej samej strony, do której podlinkowałem powyżej:

(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.
 81
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Jeszcze kilka uwag:

  • Większość funkcji CL domyślnie używa EQL, gdy nie podano testu

  • Zobacz także STRING-EQUAL, = and TREE-EQUAL

  • W centrum EQ jest zwykle porównanie wskaźników

I szorstki przewodnik:

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)

Zauważ, że dla efektywności Zwykle EQ >> EQL >> EQUALP.

 29
Author: Leslie P. Polzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-14 08:55:40

From here and my teacher ' s slides

Eq sprawdza, czy jego argumenty (reprezentowane przez ten sam fragment pamięci komputera) są tym samym symbolem, czy nie.

Na Przykład:

(eq " A " B) NIL
(eq ' RAM ' RAM) T
(eq (cons 'a 'b) (cons a 'b')); dzieje się tak dlatego, że dla obu conów wykonywane są różne wywołania, więc oczywiście będą one przydzielane różne kawałki pamięci

Eql pierwsze testy, aby sprawdzić, czy jego argumenty spełniają EQ, jeśli nie, to stara się sprawdzić, czy są liczbami tego samego typu i wartościami.

Na Przykład:

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

Uwaga a różnica :

(eq 4.0 4.0) NIL; zależy od platformy, jak opisano w pierwszej (zaakceptowanej)odpowiedzi
(eql 4.0 4.0) T ;typ i wartość argumentów są takie same

W niektórych implementacjach (eq 4.0 4.0) może zwracać true, ponieważ nie jest określone w standardzie czy implementacja powinna zachować w pamięci tylko jedną kopię liczb i znaków, tak jak ma to miejsce w przypadku symboli). z reguły nie używaj eq na cyfrach i znakach, chyba, że naprawdę wiesz, co robisz.

Equal jest funkcją porównawczą "saner". Z reguły można myśleć o tym, że mówi się o tym, czy dwa obiekty wyglądają tak samo (strukturalnie podobne, czy izomorficzne). Jest to prawdopodobnie operator, którego chcesz użyć do ogólnej równości. Informatyka zachowuje się jak eql dla liczb, znaków i symboli, ale dla list (cons) i łańcuchów mówi, czy ich elementy

Na Przykład:

(równe 4 4) T
(equal (+2 2) 4) T

Uwaga a różnica

(eql (cons " a "b) (cons" a " b)) NIL
(equal (cons 'a 'b) (cons 'A 'b)) T ; equal jest zwykle prawdziwe dla rzeczy, które drukują to samo

Equalp jest jak equalp, tylko bardziej zaawansowany. Porównanie liczb to typ nieczuły. Porównywanie znaków i łańcuchów znaków jest niewrażliwe na wielkość liter.

Na Przykład:

(equalp (cons 'a 'b) (cons 'A 'b)) T ; to samo co equal

Uwaga a różnica

Equal (4 4.0) NIL
equalp (4 4.0) T ; jako equalp traktuje liczby typu

 11
Author: A.s. Bhullar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-15 10:18:42