Common Lisp tiene muchos predicados de igualdad distintos.
Esto difiere de otros lenguajes de programación que pueden tener solo uno o dos (por ejemplo, quizá == y ===).
Algunos de estos predicados en Common Lisp son específicos de tipos, mientras que otros son genéricos.
Estos últimos son los que se tratarán aquí.
Hay cuatro predicados de igualdad genéricos y se diferencian en cuán restrictivos son con lo que consideran «igual».
Son, en orden de más restrictivo a menos restrictivo: eq, eql, equal y equalp.
Estas son unas definiciones rápidas (omitimos algunos detalles):
eq: define la igualdad como que los dos objetos son idénticos.
p. ej.:(eq 'a 'a) ; => T
(eq (list 1 2) (list 1 2)) ; => NIL
eql: define la igualdad como: dos números con el mismo tipo y valor, dos caracteres que son iguales o, para cualquier otra cosa, si son eq.
p. ej.:(eql 1 1) ; => T
(eql #\a #\a) ; => T
(eql 1 1.0) ; => NIL
(eql #\a #\A) ; => NIL
equal: define la igualdad como: dos listas son equal si cada elemento también es equal; dos strings son equal si cada elemento es eql; dos arrays son equal si son eq; todo lo demás es equal si es eql.
p. ej.:(equal (list 1 2) (list 1 2)) ; => T
(equal #(1 2) #(1 2)) ; => NIL
(equal "foo" "foo") ; => T
equalp: define la igualdad como: los strings y los caracteres se comparan sin distinguir entre mayúsculas y minúsculas; los números se comparan con cierta conversión de tipos; las listas y los arrays son equalp si cada elemento también es equalp; las estructuras, si son del mismo tipo y todas sus ranuras son equalp; y las tablas hash, si sus claves y valores son equalp.
p. ej.:(equalp "foo" "FoO") ; => T
(equalp 3 3.0) ; => T
(equalp (make-a-structure :slot1 1 :slot2 2)
(make-a-structure :slot1 1 :slot2 2)) ; => T
Leslie, el alienígena de Lisp, está programando su robot de laberintos (como suelen hacer los jóvenes alienígenas de Lisp) y necesita ayuda. El laberinto consta de una serie de salas. Cada sala ofrece una serie de puertas entre las que elegir. Cada puerta necesita una llave. Si usas la llave equivocada en una puerta, es probable que explote (no te preocupes por el robot, no sufrirá ningún daño, pero pulir las marcas de quemaduras es bastante molesto para Leslie). Si el robot no tiene ninguna llave que abra alguna puerta, ¡la sala entera explotará! (De nuevo, no te preocupes: no causará daños, pero limpiarlo será un fastidio).
Lo que tienes que hacer para ayudar a Leslie es darle al robot la llave correcta para cada sala. El robot usará la llave en cada puerta de la sala en orden y atravesará la primera puerta que se abra.
Cada test representa un laberinto y cada afirmación es una sala. Tendrás que escribir funciones de predicado que devuelvan T cuando los argumentos sean iguales y NIL cuando no lo sean.
Este laberinto tiene una sola sala. Tienes que proporcionar una función que sepa decir si dos objetos son el mismo objeto.
Por ejemplo:
a ; => "pizza"
b ; => "pizza"
(key-object-identity a a) ; => T
(key-object-identity a b) ; => NIL
porque, aunque a y b parezcan ser lo mismo, no son el mismo objeto.
Este laberinto tiene dos salas. La primera tiene una puerta que se puede abrir si tu llave sabe distinguir si dos números son estrictamente iguales entre sí. La segunda sala necesita una llave que permita cierta flexibilidad al comprobar si dos números son iguales.
Por ejemplo:
a ; => 13
b ; => 13.0
c ; => 13
(key-numbers a b) ; => NIL
(key-numbers a c) ; => T
(key-numbers-of-different-types a b) ; => T
porque, aunque a y b sean numéricamente iguales, son de tipos diferentes.
Este laberinto tiene dos salas. La primera tiene una puerta que se puede abrir si tu llave sabe distinguir si dos caracteres son estrictamente iguales entre sí. La segunda sala necesita una llave que permita comparar los caracteres sin distinguir entre mayúsculas y minúsculas.
Por ejemplo:
a ; => #\X
b ; => #\x
c ; => #\X
(key-characters a b) ; => NIL
(key-characters a c) ; => T
(key-characters-case-insensitively a b) ; => T
porque solo los predicados de igualdad muy permisivos ignoran las mayúsculas y las minúsculas al comparar dos caracteres.
Al igual que en el laberinto de los caracteres, la primera sala necesita una llave que compruebe si dos strings son iguales; la segunda sala necesita una llave que permita compararlos sin distinguir entre mayúsculas y minúsculas.
Por ejemplo:
a ; => "pizza"
b ; => "PIZZA"
c ; => "pizza"
(key-strings a b) ; => NIL
(key-strings a c) ; => T
(key-strings-case-insensitively a b) ; => T
porque solo los predicados de igualdad muy permisivos ignoran las mayúsculas y las minúsculas al comparar dos strings.
Este es un laberinto grande, con muchas salas. Cada sala necesita una llave que compruebe si los conses contienen cosas que son iguales. Cada sala comprobará la igualdad de conses con contenidos diferentes: símbolos, números, caracteres, y algunas necesitarán definiciones de igualdad más flexibles para esos contenidos.
Por ejemplo:
syms-a ; => (left . right)
syms-b ; => (up . down)
syms-c ; => (left . right)
chars-a ; => (#\x . #\y)
chars-b ; => (#\x . #\Y)
chars-c ; => (#\x . #\y)
nums-a ; => (13 . 23)
nums-b ; => (13 . 23.0)
nums-c ; => (13 . 23)
(key-conses-of-symbols syms-a syms-b) ; => NIL
(key-conses-of-symbols syms-a syms-c) ; => T
(key-conses-of-characters chars-a chars-b) ; => NIL
(key-conses-of-characters chars-a chars-c) ; => T
(key-conses-of-characters-case-insensitively
chars-a chars-b) ; => T
(key-conses-of-numbers nums-a nums-b) ; => NIL
(key-conses-of-numbers nums-a nums-c) ; => T
(key-conses-of-numbers-of-different-types
nums-a nums-b) ; => T
porque, incluso con un predicado de igualdad que mira dentro de un cons, puede que no sea lo bastante permisivo como para ignorar las mayúsculas y las minúsculas o el tipo numérico al comparar.
Este laberinto es más sencillo, con solo dos salas. La primera necesita una llave que compruebe si los arrays son los mismos arrays. La segunda necesita una llave que compruebe el contenido de los arrays.
Por ejemplo:
a ; => #[13 23]
b ; => #[13 23]
c ; => #[13 23.0]
(key-arrays a b) ; => NIL
(key-arrays a c) ; => NIL
(key-arrays-loosely a b) ; => T
(key-arrays-loosely a c) ; => T
porque solo los comparadores de igualdad muy permisivos comprueban si el contenido del array es igual.
Regístrate en Exercism para aprender y dominar Common Lisp con 27 conceptos92 ejercicios y mentoría humana real, todo gratis.