Spec-Zone.ru › Elisp

Создание и интернирование символов

Чтобы понять, как создаются символы в 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

Spec-Zone.ru

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