В чем разница между eq, eql, equal и equalp, в Common Lisp?



В чем разница между eq,eql,equal и equalp, в Common Lisp? Я понимаю, что некоторые из них проверяют типы, некоторые из них проверяют все типы, но что есть что? Когда лучше использовать, чем другие?

769   3  

3 ответов:

С Common Lisp: Предикаты Равенства

(eq x y) true если и только если x и y тот же самый идентичный объект.

The eql предикат истинен, если его аргументы eq, или если это числа одного типа с одинаковым значением, или если это символьные объекты, представляющие один и тот же символ.

The equal предикат истинен, если его аргументы структурно схожи (изоморфные) объекты. Грубое эмпирическое правило состоит в том, что два объекта равны тогда и только тогда, когда их печатные представления одинаковы.

два объекта equalp если они равны; если они являются символами и удовлетворяют char-equal, который игнорирует алфавитный регистр и некоторые другие атрибуты символов; если они являются числами и имеют одинаковое числовое значение, даже если они имеют разные типы; или если они имеют компоненты, которые все 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, когда тест не указан

  • Смотрите также строки равны, = и дерево-равной

  • в основе эквалайзера обычно лежит сравнение указателей

и приблизительного ориентира:

To compare against...      Use...

Objects/Structs            EQ

NIL                        EQ (but the function NULL is more concise and probably cheaper)

T                          EQ (or just the value but then you don't care for the type)

Precise numbers            EQL

Floats                     =

Characters                 EQL or CHAR-EQUAL

Lists, Conses, Sequences   EQ (if you want the exact same object)
                           EQUAL (if you just care about elements)

Strings                    EQUAL (case-sensitive), EQUALP (case-insensitive)
                           STRING-EQUAL (if you throw symbols into the mix)

Trees (lists of lists)     TREE-EQUAL (with appropriate :TEST argument)

обратите внимание, что для эффективности обычно EQ >> EQL >> EQUAL >> EQUALP.

с здесь и слайды моего учителя

eq проверяет, являются ли его аргументы(представленные одним и тем же фрагментом памяти компьютера) одним и тем же символом или нет.

Например:

(eq ‘A ‘B) NIL
(eq ‘RAM ‘RAM) T
(ЭИ (свод 'на 'B) (минусы на' B')) ; это потому, что разные вызовы выполняются для обоих минусов, поэтому они, очевидно, будут выделены разные куски памяти

eql первые тесты, чтобы увидеть, если его аргументы удовлетворяют EQ, если нет, он пытается увидеть, если они это числа одного типа и значения.

Например:

(eql 4 4.0) NIL
(eql 4 4) T

теперь обратите внимание на разница:

(eq 4.0 4.0) NIL; зависит от платформы, как описано в первом (принятом) ответе
(eql 4.0 4.0) T; тип и значение аргументов: то же самое

в некоторых реализациях (eq 4.0 4.0) может возвращать true, потому что в стандарте не указано, должна ли реализация хранить в памяти только одну копию чисел и символов, как это происходит с символами).как правилоне используйте эквалайзер для чисел и символов,если вы действительно знаете, что вы делаете.

равной является" более здравой " функцией сравнения. Как правило, вы можете подумайте об этом, как о том, чтобы сказать вам, выглядят ли два объекта одинаково (структурно похожие или изоморфные). Вероятно, это оператор, который вы хотите использовать для общего равенства. Он ведет себя как eql для чисел, символов и символов, но для списков (conses) и строк он сообщает, если их элементы

Например:

(равно 4 4) T
(равно (+ 2 2) 4) T

теперь обратите внимание на разница

(eql (cons ' a ' b) (cons 'a 'b)) ноль
(равенства (минусы 'а 'б) (минусы 'А 'Б)) Т ; equal обычно верно для вещей, которые печатают то же самое

equalp как равный, просто более продвинутый. Сравнение чисел является нечувствительным к типу. Сравнение символов и строк не зависит от регистра.

Например:

(equalp (cons ' a ' b) (cons 'a 'b)) T ;то же самое, что и равный

теперь обратите внимание a разница

равно (4 4.0) NIL
equalp (4 4.0) T;как equalp обрабатывает номера типа нечувствительно

Comments

    Ничего не найдено.