В чем разница между eq, eql, equal и equalp в Common Lisp?
В чем разница между eq
, eql
, equal
а также equalp
в Common Lisp? Я понимаю, что некоторые из них проверяют типы, некоторые проверяют разные типы и все такое, но какой именно? Когда один лучше использовать, чем другие?
3 ответа
Из Общего Лиспа: Предикаты Равенства
(eq x y)
верно тогда и только тогда, когдаx
а такжеy
один и тот же идентичный объект.
eql
Предикат истинен, если его аргументыeq
или если они являются числами одного типа с одинаковым значением, или если они являются символьными объектами, представляющими один и тот же символ.
equal
Предикат имеет значение true, если его аргументы являются структурно подобными (изоморфными) объектами. Грубое практическое правило состоит в том, что два объекта равны тогда и только тогда, когда их напечатанные представления одинаковы.Два объекта
equalp
если они равны; если они являются символами и удовлетворяют символу равно, что игнорирует буквенный регистр и некоторые другие атрибуты символов; если они являются числами и имеют одинаковое числовое значение, даже если они разных типов; или если у них есть компоненты, которые всеequalp
,
Вот несколько примеров с той же страницы, на которую я ссылался выше:
(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.
Еще несколько заметок:
Большинство функций CL неявно используют EQL, если тест не указан
Смотрите также STRING-EQUAL, = и TREE-EQUAL
В основе EQ обычно лежит сравнение указателей
И грубый гид:
Для сравнения с... Используйте... Объекты / Структуры EQ NIL EQ (но функция NULL более лаконична и, вероятно, дешевле) T EQ (или просто значение, но тогда вам наплевать на тип) Точные цифры EQL Плавает = Символы EQL или CHAR-EQUAL Списки, Conses, Sequence EQ (если вы хотите точно такой же объект) РАВНО (если вы просто заботитесь об элементах) Строки EQUAL (с учетом регистра), EQUALP (без учета регистра) STRING-EQUAL (если вы бросаете символы в микс) Деревья (списки списков) TREE-EQUAL (с соответствующим аргументом TEST)
Обратите внимание, что для эффективности обычно EQ >> EQL >> EQUAL >> EQUALP.
Отсюда и слайды моего учителя
eq проверяет, являются ли его аргументы (представленные одним и тем же фрагментом памяти компьютера) одним и тем же символом или нет.
Например:
(eq 'A' B) NIL
(eq 'RAM' RAM) T
(eq (минусы a 'b) (минусы a' b')); Это связано с тем, что для обоих минусов выполняются разные вызовы, поэтому им, очевидно, будут выделены разные фрагменты памяти
eql сначала проверяет, удовлетворяют ли его аргументы EQ, если нет, он пытается определить, являются ли они числами одного типа и значениями.
Например:
(eql 4 4.0) ноль
(Экл 4 4) Т
Теперь обратите внимание на разницу:
(eq 4.0 4.0) NIL; Зависит от платформы, как описано в первом (принятом) ответе
(eql 4.0 4.0) T; тип и значение аргументов одинаковы
В некоторых реализациях (например, 4.0 4.0) может возвращаться значение true, поскольку в стандарте не указано, должна ли реализация хранить в памяти только одну копию чисел и символов, как это делается с символами). Как правило , не использовать Эквивалент чисел и символов, если вы действительно не знаете, что делаете.
Равный - это более разумная функция сравнения. Как правило, вы можете думать об этом как о том, чтобы сказать вам, выглядят ли два объекта одинаково (структурно схожи или изоморфны). Вероятно, это оператор, который вы хотите использовать для общего равенства. Он ведет себя как eql для чисел, символов и символов, но для списков (значений) и строк сообщает, если их элементы
Например:
(равно 4 4) Т
(равно (+ 2 2) 4) Т
Теперь обратите внимание на разницу
(eql (минусы 'a' b) (минусы 'a' b)) NIL
(равно (минусы 'a' b) (минусы 'a 'b)) T; равное обычно верно для вещей, которые печатают одинаково
Равный как равный, только более продвинутый. Сравнение чисел не зависит от типа. Сравнение символов и строк не учитывает регистр.
Например:
(equp (минусы 'a' b) (минусы 'a 'b)) T; такой же как равный
Теперь обратите внимание на разницу
равно (4 4.0) ноль
равно (4,0) T; Так как equp относится к типу чисел нечувствительно