Common Lisp, come altri linguaggi, ha una serie di regole per decidere se due oggetti sono lo «stesso». Queste regole definiscono quattro livelli, ognuno con una funzione che esegue quel livello di controllo. I livelli sono ordinati dal più rigoroso al più permissivo.
eqIl primo livello è l'identità dell'oggetto.
Questa uguaglianza si verifica con la funzione eq.
I due oggetti di cui si verifica l'uguaglianza devono essere esattamente lo stesso oggetto:
(eq 'apples 'apples) ; => T
(eq 'apples 'oranges) ; => NIL
(eq '(a b c) '(a b c) ; => NIL (these two lists have the same contents but are not the same list)
(let ((list1 '(a b c)) (list2 list1))
(eq list1 list2)) ; => T (these two lists are the same list)
eqlIl secondo livello aggiunge l'uguaglianza di numeri e caratteri.
Questa uguaglianza si verifica con la funzione eql.
Il modo in cui viene eseguito il controllo dipende dai tipi degli argomenti:
eq sono anche eql
eql se hanno lo stesso tipo e lo stesso valoreeql se rappresentano lo stesso carattere.(eql 1 1) ; => T
(eql 1 1/1) ; => NIL (one number is an integer, the other a rational)
(eql #\c #\c) ; => T
(eql #\c #\C) ; => NIL (case is different)
Ci si potrebbe chiedere perché numeri e caratteri non vengano confrontati per identità dell'oggetto con eq.
Lo standard Common Lisp consente alle implementazioni di copiare numeri e caratteri, se scelgono di farlo.
Quindi 0 e 0 potrebbero non essere eq, dato che possono essere istanze diverse del numero 0.
equalIl terzo livello verifica la somiglianza strutturale.
Questa uguaglianza si verifica con equal.
Il modo in cui viene eseguito il controllo dipende dai tipi degli argomenti:
eq
eql
equal se i loro elementi sono equal.
Questo viene fatto in modo ricorsivo.equal se i loro elementi sono eql
eq
equal se sono funzionalmente equivalenti.
(Qui c'è spazio per un comportamento dipendente dall'implementazione per quanto riguarda la sensibilità alle maiuscole delle stringhe che compongono i componenti dei pathname.)eq
(equal '(a (b c)) '(a (b c))) ; => T (conses are equal if their contents are equal)
(equal "hello" "hello") ; => T
(equal "hello" "HELLO") ; => NIL
(equal #(1 2 3) #(1 2 3)) ; => NIL (arrays are equal only if eq)
(equal #P"foo/bar.md" #P"foo/bar.md") ; => T (pathnames are equal if "functionally equivalent"
equalpIl quarto livello di uguaglianza, il più permissivo, si verifica con equalp.
Il modo in cui viene eseguito il controllo dipende dai tipi:
equalp, allora sono equalp
equalp se hanno lo stesso valore, anche se non sono dello stesso tipoequalp se i loro elementi sono equalp.
Questo viene fatto in modo ricorsivo.equalp se hanno lo stesso numero di dimensioni, quelle dimensioni sono le stesse e ogni elemento è equalp.equalp se hanno la stessa classe e gli stessi slot, e ognuno di quegli slot è equalp tra le due strutture.equalp se entrambe hanno la stessa funzione :test, hanno le stesse chiavi (confrontate con quella funzione :test) e quelle chiavi hanno gli stessi valori, confrontati con equalp.(equalp 1 1.0) ; => T
(equalp #\c #\C) ; => T
(equalp "hello" "HELLO") ; => T
(equalp #(1 2 3) #(1.0 2.0 3.0)) ; => T (arrays contain elements which are `equalp`)
(equal #S(TEST :SLOT1 'a :SLOT2 'b)
#S(TEST :SLOT1 'a :SLOT2 'b)) ; => T (structures of the same class with slots that have values which are `equalp`)
Quelle sopra sono le funzioni di uguaglianza «generiche».
Funzionano, come definito, per qualsiasi tipo.
Questo può essere utile quando si scrive codice generico che non conosce i tipi degli oggetti che confronterà fino al momento dell'esecuzione.
Tuttavia, è generalmente considerato «migliore stile» usare funzioni di uguaglianza specifiche per tipo quando si conoscono i tipi confrontati.
Per esempio string= invece di equal.
Queste funzioni saranno presentate e discusse nei concetti pertinenti.