Создание и интернирование символов
Чтобы понять, как создаются символы в GNU Emacs Lisp, нужно знать, как Lisp считывает их. Lisp должен гарантировать, что каждый раз при считывании одной и той же последовательности символов в одном и том же контексте он находит один и тот же символ. В противном случае возникнет полная путаница.
Когда считыватель Lisp встречает в исходном коде имя, ссылающееся на символ, он ищет это имя в таблице, называемой obarray, чтобы найти символ, который имел в виду программист. Obarray — это неупорядоченный контейнер символов, индексируемых по имени.
Считыватель Lisp также учитывает «сокращения». Если программист их задал, считыватель может найти символ, даже если его имя в исходном коде представлено не полностью. См. Сокращения.
Если символ с нужным именем найден, считыватель использует его. Если в obarray нет символа с таким именем, считыватель создает новый символ и добавляет его в obarray. Поиск или добавление символа с определенным именем называется его интернированием, а сам символ — интернированным символом.
Интернирование гарантирует, что в каждой obarray есть только один символ с определенным именем. Могут существовать другие символы с таким же именем, но не в той же obarray. Таким образом, считыватель получает одни и те же символы для одних и тех же имен, пока вы продолжаете считывать их с помощью той же obarray.
Обычно интернирование происходит автоматически при считывании, но иногда это может потребоваться другим программам. Например, после того как команда M-x получает имя команды в виде строки с помощью минибуфера, она интернирует эту строку, чтобы получить интернированный символ с таким именем. Другой пример: гипотетическая программа телефонного справочника могла бы интернировать имя каждого найденного человека как символ, даже если в obarray его нет, чтобы прикрепить к этому новому символу сведения, например дату последнего поиска.
Ни одна obarray не содержит все символы; на самом деле некоторые символы не входят ни в одну obarray. Они называются неинтернированными символами. У неинтернированного символа те же четыре ячейки, что и у других символов; однако получить к нему доступ можно только найдя его в каком-либо другом объекте или в качестве значения переменной. Неинтернированные символы иногда полезны при создании кода Lisp; см. ниже.
Примечание о Common Lisp: В отличие от Common Lisp, Emacs Lisp не позволяет интернировать одно и то же имя в нескольких разных «пакетах», создавая таким образом несколько символов с одинаковым именем, но в разных пакетах. В Emacs Lisp используется другая система пространств имен, называемая «сокращениями» (см. Сокращения).
- Функция: obarray-make &optional size
Эта функция создает и возвращает новую obarray. Необязательный аргумент size можно использовать, чтобы указать предполагаемое количество символов, которые она будет содержать. Однако, поскольку размер obarray автоматически увеличивается по мере необходимости, это редко дает какие-либо преимущества.
- Функция: obarrayp object
Эта функция возвращает
t, если object является obarray, иnilв противном случае.
Большинство приведенных ниже функций принимают в качестве аргументов имя, а иногда и obarray. Возникает ошибка wrong-type-argument, если имя не является строкой или если obarray не является объектом obarray.
- Функция: symbol-name symbol
-
Эта функция возвращает строку, являющуюся именем symbol. Например:
(symbol-name 'foo) ⇒ "foo"Предупреждение: Никогда не изменяйте строку, возвращенную этой функцией. Это может нарушить работу Emacs и даже привести к аварийному завершению Emacs.
Создание неинтернированного символа полезно при генерации кода Lisp, поскольку неинтернированный символ, используемый в качестве переменной в создаваемом коде, не может совпасть ни с одной переменной, используемой в других программах Lisp.
- Функция: make-symbol name
-
Эта функция возвращает вновь выделенный неинтернированный символ с именем name (которое должно быть строкой). Его значение и определение функции не заданы, а список свойств равен
nil. В приведенном ниже примере значениеsymнеeqсfoo, поскольку это отдельный неинтернированный символ, имя которого также — ‘foo’.(setq sym (make-symbol "foo")) ⇒ foo (eq sym 'foo) ⇒ nil
- Функция: gensym &optional prefix
Эта функция возвращает символ, используя
make-symbol. Его имя формируется добавлениемgensym-counterк prefix с последующим увеличением этого счетчика, что гарантирует, что ни два вызова этой функции не создадут символы с одинаковыми именами. По умолчанию префикс равен"g".
Чтобы избежать проблем при случайном интернировании печатного представления сгенерированного кода (см. Печатное представление и синтаксис чтения), рекомендуется использовать gensym вместо make-symbol.
- Функция: intern name &optional obarray
-
Эта функция возвращает интернированный символ с именем name. Если в obarray obarray нет такого символа,
internсоздает новый символ, добавляет его в obarray и возвращает. Если obarray не указан, используется значение глобальной переменнойobarray.(setq sym (intern "foo")) ⇒ foo (eq sym 'foo) ⇒ t (setq sym1 (intern "foo" other-obarray)) ⇒ foo (eq sym1 'foo) ⇒ nil
Примечание о Common Lisp: В Common Lisp можно интернировать существующий символ в obarray. В Emacs Lisp это невозможно, поскольку аргументом
internдолжна быть строка, а не символ.
- Функция: intern-soft name &optional obarray
-
Эта функция возвращает символ в obarray с именем name или
nil, если в obarray нет символа с таким именем. Поэтому с помощьюintern-softможно проверить, интернирован ли уже символ с заданным именем. Если obarray не указан, используется значение глобальной переменнойobarray.Аргументом name также может быть символ; в этом случае функция возвращает name, если он интернирован в указанной obarray, и
nilв противном случае.(intern-soft "frazzle") ; No such symbol exists. ⇒ nil (make-symbol "frazzle") ; Create an uninterned one. ⇒ frazzle
(intern-soft "frazzle") ; That one cannot be found. ⇒ nil(setq sym (intern "frazzle")) ; Create an interned one. ⇒ frazzle(intern-soft "frazzle") ; That one can be found! ⇒ frazzle(eq sym 'frazzle) ; And it is the same one. ⇒ t
- Переменная: obarray
Эта переменная содержит стандартную obarray, используемую
internиread.
- Функция: mapatoms function &optional obarray
-
Эта функция вызывает function один раз для каждого символа в obarray obarray. Затем она возвращает
nil. Если obarray не указана, по умолчанию используется значениеobarray— стандартной obarray для обычных символов.(setq count 0) ⇒ 0 (defun count-syms (s) (setq count (1+ count))) ⇒ count-syms (mapatoms 'count-syms) ⇒ nil count ⇒ 1871Другой пример использования
mapatomsсм. в разделеdocumentationв Доступ к строкам документации.
- Функция: unintern symbol obarray
-
Эта функция удаляет symbol из obarray obarray. Если
symbolна самом деле не входит в obarray,uninternничего не делает. Если obarray равнаnil, используется текущая obarray.Если вместо символа в качестве symbol передана строка, она обозначает имя символа. В этом случае
uninternудаляет символ (если он есть) в obarray с таким именем. Если такого символа нет,uninternничего не делает.Если
uninternдействительно удаляет символ, она возвращаетt. В противном случае она возвращаетnil.
- Функция: obarray-clear obarray
Эта функция удаляет все символы из obarray.
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/Creating-Symbols.html