Spec-Zone.ru › Elisp

Предикаты равенства

Здесь мы описываем функции, проверяющие равенство двух объектов. Другие функции проверяют равенство содержимого объектов определённых типов, например строк. О таких предикатах см. соответствующую главу, в которой описывается тип данных.

Функция: eq object1 object2

Эта функция возвращает t, если object1 и object2 являются одним и тем же объектом, и nil в противном случае.

Если object1 и object2 — символы с одинаковым именем, обычно это один и тот же объект, но см. раздел Создание и интернирование символов, где описаны исключения. Для других типов, не являющихся числами (например, списков, векторов и строк), два аргумента с одинаковым содержимым или элементами не обязательно являются eq друг другу: они являются eq только в том случае, если это один и тот же объект, то есть изменение содержимого одного из них отразится таким же изменением содержимого другого.

Если object1 и object2 — числа разных типов или значений, они не могут быть одним и тем же объектом, и eq возвращает nil. Если это фиксимы с одинаковым значением, то они являются одним и тем же объектом, и eq возвращает t. Если они были вычислены отдельно, но имеют одинаковое значение и одинаковый числовой тип, отличный от типа фиксиму, то они могут быть как одним и тем же объектом, так и разными объектами, а eq возвращает t или nil в зависимости от того, создал интерпретатор Lisp один объект или два.

Если object1 или object2 — символ с позицией, eq рассматривает его как обычный символ, когда symbols-with-pos-enabled не-nil (см. раздел Символы с позицией).

(eq 'abc 'abc)  ⇒ t
(eq 'abc 'ABC)  ⇒ nil
(eq ?A ?A)      ⇒ t
(eq 3 3)        ⇒ t

Равные числа, не являющиеся фиксимами, могут быть как одним и тем же объектом, так и разными объектами:

(eq 3.0 3.0)                    ⇒ t or nil
(eq (expt 10 50) (expt 10 50))  ⇒ t or nil

Вновь созданные изменяемые объекты различны:

(eq (list 1 2 3) (list 1 2 3))      ⇒ nil
(eq (point-marker) (point-marker))  ⇒ nil

Равные константы других типов могут быть как одним и тем же объектом, так и разными объектами:

(eq "abc" "abc")        ⇒ t or nil
(eq '(1 2 3) '(1 2 3))  ⇒ t or nil
(eq [1 2 3] [1 2 3])    ⇒ t or nil

кроме случаев, когда это одна и та же литеральная константа:

(let ((x "abc"))    (eq x x))  ⇒ t
(let ((x '(1 2 3))) (eq x x))  ⇒ t
(let ((x [1 2 3]))  (eq x x))  ⇒ t

Функция make-symbol возвращает неинтернированный символ, отличный от символа, который используется при записи этого имени в выражении Lisp. Различные символы с одинаковым именем не являются eq. См. раздел Создание и интернирование символов.

(eq (make-symbol "foo") 'foo)
     ⇒ nil

Байт-компилятор Emacs Lisp может объединять идентичные литеральные объекты, например литеральные строки, заменяя их ссылками на один и тот же объект. В результате байт-компилированный код будет сравнивать такие объекты как eq, а интерпретируемая версия того же кода — нет. Поэтому ваш код никогда не должен полагаться на то, что объекты с одинаковым литеральным содержимым являются или не являются eq и eq; вместо этого следует использовать функции, сравнивающие содержимое объектов, например equal, описанную ниже. Аналогично, ваш код не должен изменять литеральные объекты (например, добавлять текстовые свойства к литеральным строкам), поскольку это может повлиять на другие литеральные объекты с таким же содержимым, если байт-компилятор объединит их.

Функция: equal object1 object2

Эта функция возвращает t, если компоненты object1 и object2 равны, и nil в противном случае. В то время как eq проверяет, являются ли аргументы одним и тем же объектом, equal заглядывает внутрь различных аргументов, чтобы проверить, совпадают ли их элементы или содержимое. Поэтому, если два объекта являются eq, они являются equal, но обратное верно не всегда.

(equal 'foo 'foo)
     ⇒ t
(equal 456 456)
     ⇒ t
(equal "asdf" "asdf")
     ⇒ t
(equal '(1 (2 (3))) '(1 (2 (3))))
     ⇒ t
(equal [(1 2) 3] [(1 2) 3])
     ⇒ t
(equal (point-marker) (point-marker))
     ⇒ t

Функция equal сравнивает строки и булевы векторы по значению. Числа сравниваются по типу и числовому значению с помощью eql. Списки, cons-ячейки, векторы, записи, маркеры, таблицы символов, объекты шрифтов и функциональные объекты (замыкания) сравниваются рекурсивно с помощью equal для составляющих их частей.

При сравнении строк учитывается регистр, но не текстовые свойства — сравниваются только символы в строках. См. раздел Текстовые свойства. Чтобы также сравнивать текстовые свойства, используйте equal-including-properties. По техническим причинам однобайтовая и многобайтовая строки являются equal тогда и только тогда, когда содержат одинаковую последовательность кодов символов и все эти коды находятся в диапазоне от 0 до 127 (ASCII).

(equal "asdf" "ASDF")
     ⇒ nil

Если object1 или object2 содержит символы с позицией, equal рассматривает их как обычные символы, когда symbols-with-pos-enabled не-nil. В противном случае equal сравнивает два символа с позицией, сравнивая их компоненты. См. раздел Символы с позицией.

Другие объекты считаются equal только в том случае, если они являются eq. Например, два различных буфера никогда не считаются equal, даже если их текстовое содержимое совпадает.

Для equal равенство определяется рекурсивно; например, для двух cons-ячеек x и y (equal x y) возвращает t тогда и только тогда, когда оба приведённых ниже выражения возвращают t:

(equal (car x) (car y))
(equal (cdr x) (cdr y))

Таким образом, сравнение очень глубоко вложенных объектов может привести к глубокой рекурсии и вызвать ошибку.

Функция: equal-including-properties object1 object2

Эта функция во всех случаях ведёт себя как equal, но дополнительно требует, чтобы две строки для признания равными имели одинаковые текстовые свойства.

(equal "asdf" (propertize "asdf" 'asdf t))
     ⇒ t
(equal-including-properties "asdf"
                            (propertize "asdf" 'asdf t))
     ⇒ nil

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Equality-Predicates.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API