Was ist der Unterschied zwischen Gleichung, Gleichung, Gleich und Gleich in Common Lisp?

73

Was ist der Unterschied zwischen eq, eql, equalund equalp, in Common Lisp? Ich verstehe, dass einige von ihnen Typen prüfen, andere typübergreifend prüfen und all das, aber welches ist welches? Wann ist einer besser zu bedienen als die anderen?

Cristián Romo
quelle

Antworten:

81

Aus Common Lisp: Gleichheitsprädikate

(eq x y)wenn wahr ist , und nur , wenn xund yist das gleiche identische Objekt.

Das eqlPrädikat ist wahr, wenn seine Argumente sind eqoder wenn es sich um Zahlen desselben Typs mit demselben Wert handelt oder wenn es sich um Zeichenobjekte handelt, die dasselbe Zeichen darstellen.

Das equalPrädikat ist wahr, wenn seine Argumente strukturell ähnliche (isomorphe) Objekte sind. Eine grobe Faustregel lautet, dass zwei Objekte genau dann gleich sind, wenn ihre gedruckten Darstellungen gleich sind.

Zwei Objekte sind, equalpwenn sie gleich sind; wenn sie Zeichen sind und char-gleich erfüllen, wobei die alphabetische Groß- und Kleinschreibung und bestimmte andere Attribute von Zeichen ignoriert werden; wenn es sich um Zahlen handelt, die denselben numerischen Wert haben, auch wenn sie unterschiedlichen Typs sind; oder wenn sie Komponenten haben, die alle sind equalp.

Hier sind einige Beispiele von derselben Seite, auf die ich oben verlinkt habe:

(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.
Bill die Eidechse
quelle
29

Noch ein paar Anmerkungen:

  • Die meisten CL-Funktionen verwenden implizit EQL, wenn kein Test angegeben ist

  • Siehe auch STRING-EQUAL, = und TREE-EQUAL

  • Im Zentrum von EQ steht normalerweise ein Zeigervergleich

Und eine grobe Anleitung:

Zum Vergleich mit ... Verwenden Sie ...

Objekte / Strukturen EQ

NIL EQ (aber die Funktion NULL ist prägnanter und wahrscheinlich billiger)

T EQ (oder nur der Wert, aber dann interessiert Sie der Typ nicht)

Genaue Zahlen EQL

Floats =

Zeichen EQL oder CHAR-EQUAL

Listen, Nachteile, Sequenzen EQ (wenn Sie genau das gleiche Objekt möchten)
                           GLEICH (wenn Sie sich nur für Elemente interessieren)

Strings EQUAL (Groß- und Kleinschreibung beachten), EQUALP (Groß- und Kleinschreibung beachten)
                           STRING-EQUAL (wenn Sie Symbole in die Mischung werfen)

Bäume (Listen von Listen) TREE-EQUAL (mit entsprechendem: TEST-Argument)

Beachten Sie, dass aus Effizienzgründen normalerweise EQ >> EQL >> EQUAL >> EQUALP.

Leslie P. Polzer
quelle
11

Von hier und den Folien meines Lehrers

eq testet, ob seine Argumente (dargestellt durch denselben Teil des Computerspeichers) dasselbe Symbol sind oder nicht.

Zum Beispiel:

(Gleichung 'A' B) NIL
(Gleichung 'RAM' RAM) T
(Gleichung (Nachteile 'a' b) (Nachteile a 'b')); Dies liegt daran, dass für beide Nachteile unterschiedliche Aufrufe getätigt werden, sodass ihnen offensichtlich unterschiedliche Speicherblöcke zugewiesen werden

eql testet zuerst, ob seine Argumente EQ erfüllen. Wenn nicht, versucht es zu sehen, ob es sich um Zahlen desselben Typs und derselben Werte handelt.

Zum Beispiel:

(Gleichung 4 4.0) NIL
(Gleichung 4 4) T.

Beachten Sie nun einen Unterschied :

(Gleichung 4.0 4.0) NIL; Abhängig von der Plattform, wie in der ersten (akzeptierten) Antwort beschrieben
(Gleichung 4.0 4.0) T; Typ und Wert der Argumente sind gleich

Bei einigen Implementierungen (Gleichung 4.0 4.0) wird möglicherweise true zurückgegeben, da im Standard nicht festgelegt ist, ob eine Implementierung nur eine Kopie von Zahlen und Zeichen im Speicher behalten soll, wie dies bei Symbolen der Fall ist. Als Faustregel wird dies nicht verwendet Gleichung für Zahlen und Zeichen , es sei denn, Sie wissen wirklich, was Sie tun.

gleich ist eine "vernünftigere" Vergleichsfunktion. Als Faustregel können Sie sich vorstellen, dass zwei Objekte gleich aussehen (strukturell ähnlich oder isomorph). Dies ist wahrscheinlich der Operator, den Sie für die allgemeine Gleichstellung verwenden möchten. Es verhält sich wie eql für Zahlen, Zeichen und Symbole, aber für Listen (conses) und Strings sagt es, ob ihre Elemente

Zum Beispiel:

(gleich 4 4) T
(gleich (+ 2 2) 4) T.

Beachten Sie nun einen Unterschied

(Gleichung (Nachteile 'a' b) (Nachteile 'a' b)) NIL
(gleich (Nachteile 'a' b) (Nachteile 'a' b)) T; Gleich gilt normalerweise für Dinge, die gleich drucken

Equalp ist wie gleich, nur fortgeschrittener. Der Vergleich von Zahlen ist typunempfindlich. Beim Vergleich von Zeichen und Zeichenfolgen wird die Groß- und Kleinschreibung nicht berücksichtigt.

Zum Beispiel:

(gleich (Nachteile 'a' b) (Nachteile 'a' b)) T; gleich wie gleich

Beachten Sie nun einen Unterschied

gleich (4 4,0) NIL
gleich (4 4,0) T; Als Equalp behandelt Zahlen Typ unempfindlich

Als Bhullar
quelle