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

Символы бывают двух видов. Интернированный символ – это символ, который может быть задан с помощью имени и каталога (пакета) и непосредственно имени символа.

A request to locate a symbol with that print name results in the same (eq) symbol. Every time input is read with the function read, and that print name appears, it is read as the same symbol. This property of symbols makes them appropriate to use as names for things and as hooks on which to hang permanent data objects (using the property list, for example).

Обращение к символу с некоторым именем возвращает символ, равный eq необходимому. Каждый раз когда функция read встречает строку для символа, они находит соотвествующий данной строке символ. FIXME

Интернированные символы обычно создаются автоматически. Во время первого обращения к символу в системе пакетов (с помощью read, например), данный символ создаётся автоматически. Для обращения к интернированному символу используется функция inter, или другая с ней связанная.

Несмотря на то, что интернированные символы используются чаще всего, они не будут больше здесь рассматриваться. Для подробной информации смотрите главу 11.

Дезинтернированный символ является символом, используемым в качестве объекта данных, без связи с каталогом (он не имеет родительского пакета). Неинтернированный символ выводится как #: с последующим выводимым именем.

[Функция] make-symbol print-name

(make-symbol print-name) создаёт новый неинтернированный символ, у которого выводимое имя является строкой print-name. Полученный символ не имеет значения функции (unbound) и пустой список свойств.

Строка, переданная в аргументе, может использоваться сразу, либо сначала копироваться. Это зависит от реализации. Пользователь не может полагаться на то, что (symbol-name (make-symbol x)) равно eq x, но и также не может изменять строку переданную в качестве аргумента для make-symbol. ___________________________________________________________

Заметка для реализации: Реализация может, например, скопировать строку в область «только для чтения», полагаясь на то, что строка никогда не будет изменена.

___________________________________________________________________________________________________________

[Функция] copy-symbol sym &optional copy-props

Эта функция возвращает новый неинтернированный символ с тем же выводимым именем, что sym.

X3J13 voted in March 1989 that the print name of the new symbol is required to be the same only in the sense of string=; in other words, an implementation is permitted (but not required) to make a copy of the print name. User programs should not assume that the print names of the old and new symbols will be eq, although they may happen to be eq in some implementations.

Если copy-props не-nil, тогда начальное значение и определение функции нового символа будут те же, что и в переданном sym, а список свойств будет скопирован из исходного символа.

При использовании данной функции копируются cons-ячейки только верхнего уровня.

It is as if (copy-list (symbol-plist sym)) were used as the property list of the new symbol.

Если copy-props является nil (по-умолчанию), тогда новый символ не будет связан, не будет иметь определения функции, и список свойств будет пуст.


[Функция] gensym &optional x

gensym создаёт выводимое имя и создаёт новый символ с этим именем. Она возвращает новый неинтернированный символ.

Созданное имя содержит префикс (по-умолчанию G), с последующим десятичным представлением числа.

gensym обычно используется для создания символа, который не виден пользователю, и его имя не имеет важности. Необязательный аргумент используется нечасто. Имя образовано от «генерация символа», и символы созданные, таким образом, часто называются «gensyms».

Если необходимо, чтобы сгенерированные символы были интернированными и отличными от существующих символов, тогда удобно использовать функцию gentemp.

X3J13 voted in March 1989 to alter the specification of gensym so that supplying an optional argument (whether a string or a number) does not alter the internal state maintained by gensym. Instead, the internal counter is made explicitly available as a variable named *gensym-counter*.

If a string argument is given to gensym, that string is used as the prefix; otherwise “G” is used. If a number is provided, its decimal representation is used, but the internal counter is unaffected. X3J13 deprecates the use of a number as an argument.


[Переменная] *gensym-counter*

Переменная хранит состояние счётчика для функции gensym. gensym использует десятичное представление этого значения в качестве части имени генерируемого символа, а затем наращивает этот счётчик.

Первоначальное значение этой переменной зависит от реализации, но должно быть неотрицательным целым.

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


[Функция] gentemp &optional prefix package

gentemp, как и gensym, создаёт и возвращает новый символ. gentemp отличается от gensym в том, что возвращает интернированный символ (смотрите intern) в пакете package (который по-умолчанию является текущим, смотрите *package*). gentemp гарантирует, что символ будет новым, и не существовал ранее в указанном пакете. Она также использует счётчик, однако если полученный символ уже существует счётчик наращивается, и действия повторяются, пока не будет найдено имя ещё не существующего символа. Сбросить счётчик невозможно. Кроме того, префикс для gentemp не сохраняется между вызовами. Если аргумент prefix опущен, то используется значение по-умолчанию T.


[Функция] symbol-package sym

Для заданного символа возвращает содержимое ячейки пакета. Результат может быть объектом пакета или nil.


[Функция] keywordp object

Аргумент может быть любым Lisp’овым объектом. Предикат keywordp истинен, если аргумент является символом и этот символ является ключевым (значит, что принадлежит пакету ключевых символов). Ключевые символы — это символы, которые записываются с двоеточием в начала. Каждый ключевой символ является константой, в смысле, что выполняются сами в себя. Смотрите constantp.