web-dev-qa-db-fra.com

Quelle est la différence entre eq, eql, equal et equalp, en Common Lisp?

Quelle est la différence entre eq, eql, equal et equalp, en Common Lisp? Je comprends que certains d'entre eux vérifient les types, certains vérifient les types et tout cela, mais lequel est lequel? Quand est-il préférable d'utiliser l'un que les autres?

69
Cristián Romo

De LISP commun: prédicats d'égalité

(eq x y) est vrai si et seulement si x et y sont le même objet identique.

Le prédicat eql est vrai si ses arguments sont eq, ou si ce sont des nombres du même type avec la même valeur, ou si ce sont des objets de caractère qui représentent le même caractère.

Le prédicat equal est vrai si ses arguments sont des objets structurellement similaires (isomorphes). Une règle générale est que deux objets sont égaux si et seulement si leurs représentations imprimées sont les mêmes.

Deux objets sont equalp s'ils sont égaux; s'ils sont des caractères et satisfont au caractère égal, ce qui ignore la casse alphabétique et certains autres attributs des caractères; s'il s'agit de nombres et ont la même valeur numérique, même s'ils sont de types différents; ou s'ils ont des composants qui sont tous equalp.

Voici quelques exemples de la même page que j'ai liée à ci-dessus:

(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.
76
Bill the Lizard

Quelques notes supplémentaires:

  • La plupart des fonctions CL utilisent implicitement EQL quand aucun test n'est spécifié

  • Voir aussi STRING-EQUAL, = et TREE-EQUAL

  • Au cœur de l'égalisation se trouve généralement une comparaison de pointeurs

Et un guide approximatif:

 Pour comparer avec ... Utilisez ... 
 
 Objets/Structures EQ 
 
 NIL EQ (mais la fonction NULL est plus concise et probablement moins cher) 
 
 T EQ (ou juste la valeur, mais vous ne vous souciez pas du type) 
 
 Numéros précis EQL 
 
 Flotteurs = 
 
 Caractères EQL ou CHAR-EQUAL 
 
 Listes, Conses, Séquences EQ (si vous voulez exactement le même objet) 
 EQUAL (si vous vous souciez uniquement des éléments) 
 
 Chaînes EQUAL (sensible à la casse), EQUALP (ne respectant pas la casse) 
 STRING-EQUAL (si vous lancez des symboles dans le mix.) 
 
 Arbres (listes de listes) TREE-EQUAL (avec l'argument TEST approprié) 

Notez que pour l'efficacité généralement EQ >> EQL >> EQUAL >> EQUALP.

28
Leslie P. Polzer

De ici et les diapositives de mon professeur

eq teste pour voir si ses arguments (représentés par le même bloc de mémoire d'ordinateur) sont le même symbole ou non.

Par exemple:

(eq "A" B) NUL
(eq ‘RAM’ RAM) T
(eq (contre 'a' b) (contre a 'b')); Ceci est dû au fait que différents appels sont effectués pour les deux inconvénients, de sorte qu'ils se verront évidemment allouer différents morceaux de mémoire

eql teste d'abord si ses arguments satisfont EQ, sinon, il essaie de voir s'il s'agit de nombres du même type et de mêmes valeurs.

Par exemple:

(eql 4 4.0) NUL
(eql 4 4) T

Notez maintenant une différence :

(eq 4.0 4.0) NIL; Dépend de la plateforme comme décrit dans la première réponse (acceptée)
(eql 4.0 4.0) T; le type et la valeur des arguments sont les mêmes

Sur certaines implémentations (eq 4.0 4.0) peut renvoyer true car il n'est pas spécifié dans la norme si une implémentation doit conserver une seule copie des nombres et des caractères en mémoire, comme elle le fait avec les symboles). n'utilisez pas d'égalisation sur les chiffres et les caractères , à moins que vous sachiez vraiment ce que vous faites.

égal est une fonction de comparaison "plus saine". En règle générale, vous pouvez penser que cela vous indique si deux objets se ressemblent (structurellement similaires ou isomorphes). C'est probablement l'opérateur que vous souhaitez utiliser pour l'égalité générale. Il se comporte comme eql pour les nombres, les caractères et les symboles, mais pour les listes (conses) et les chaînes il indique si leurs éléments

Par exemple:

(égal 4 4) T
(égal (+ 2 2) 4) T

Notez maintenant une différence

(eql (contre 'a' b) (contre 'a' b)) NUL
(égal (contre 'a' b) (contre 'a' b)) T; égal est généralement vrai pour les choses qui s'impriment de la même façon

equalp est comme égal, juste plus avancé. La comparaison des nombres est insensible au type. La comparaison des caractères et des chaînes est insensible à la casse.

Par exemple:

(equalp (contre 'a' b) (contre 'a' b)) T; identique à égal

Notez maintenant une différence

égal (4 4,0) NUL
equalp (4 4,0) T; Comme equalp traite les nombres de manière insensible

11
A.s. Bhullar