Common Lisp предоставляет множество типов для объектов данных.
Необходимо подчеркнуть, что в Lisp’е типизированы данные, а не
переменные. Любая переменная может содержать данные любого типа.
(Можно указать явно, что некоторая переменная фактически может
содержать только один или конечное множество типов объектов.
Однако, такая декларация может быть опущена, и программа будет
выполняться корректно. Такая декларация содержит рекомендации от
пользователя, и это может быть полезным при оптимизации. Смотрите
declare.)
В Common Lisp’е тип данных является (возможно бесконечным)
множеством Lisp объектов. Многие объекты Lisp’а принадлежат к более чем
одному множеству типов, так что иногда не имеет смысла спрашивать тип
объекта; вместо этого задаётся вопрос о принадлежности объекта к
нужному типу. Предикат typep может использоваться для определения
принадлежности объекта к заданному типу, а функция type-of возвращает
тип, к которому принадлежит заданный объект.
Типы данных в Common Lisp сложены в иерархию (фактически в порядке
убывания объёма) определённую отношениями подмножеств. Несомненно
множества объектов, такие как множество чисел и множество строк
заслуживают идентификаторов. Для многих этих идентификаторов
используются символы (здесь и далее, слово «символ» ссылается на тип
Lisp’овых объектов символ, известный также как литеральный атом). См.
главу 4 подробно описывающую определения типов.
Множество все объектов определяется символом t. Пустой тип данных,
который не содержит объектов обозначается с помощью nil.
Следующие категории объектов Common Lisp’а в особенности интересны:
числа (numbers), знаки (characters), символы (symbols), списки (lists),
массивы (arrays), структуры (structures) и функции (functions). Другие типы
тоже, конечно, интересны. Некоторые из этих категорий имеют много
подразделов. Так же есть стандартные типы, которые определены как
объединение двух и более данных категорий. Вышеупомянутые категории,
являясь типами объектов, менее «реальны» чем другие типы данных. Они
просто составляют объединения типов для наглядности.
Вот краткое изложение различных Common Lisp’овых типов данных.
Оставшиеся разделы данной главы рассматривают типы более детально, а
также описывают нотации для объектов для каждого типа. Описание
Lisp’овых функций, что оперируют объектами данных каждого типа будет
даваться в следующих главах.
- Числа имеют различные формы и представления. Common Lisp
предоставляет целочисленный (integer) тип данных: любое целое
число, положительное или отрицательное ограничено размерами
памяти (преимущественно равными ширине машинного слова).
Также предоставляется рациональный или дробный (rational)
тип данных: это отношение двух целых чисел, не являющееся
целым числом. Также предоставляются числа с плавающей точкой
различных интервалов и точностей. И наконец, в языке также есть
комплексные числа.
- Строковые символы представляют печатные символы, такие как
буквы или управляющие форматированием символы. Строки
являются одномерными массивами символов. Common Lisp
предоставляет богатое множество символов, включая способы
представления различных стилей печати.
- Символы (иногда для ясности называемые атомные символы
(atomic symbols)) являются именованными объектами данных. Lisp
предоставляет механизм определяющий местоположение объекта
символа по заданному имени (в форме строки). У символов есть
списки свойств, которые фактически позволяют использовать
символы в качестве структур, с расширяемым множеством имён
полей, каждое из которых может быть любым Lisp объектом.
Символы также служат для именования функций и переменных в
программе.
- Списки
это последовательность, представленная в форме связанных ячеек,
называемых cons-ячейками. Для обозначения пустого списка
служит специальный объект (обозначаемый символом nil). Все
остальные списки создаются рекурсивно, с помощью добавления
новых элементов в начало существующего списка. Это происходит
так: создаётся новая cons-ячейка, которая является объектом,
имеющим два компонента, называемых car и cdr. Car может
хранить, что угодно, а cdr создан для хранения указателя на
существующий ранее список. (Cons-ячейки могут использоваться
для хранения записи структуры из двух элементов, но это не
главное их предназначение.)
- Массивы - это n-мерные коллекции объектов. Массив может иметь
любое неотрицательное количество измерений и индексироваться
с помощью последовательности целых чисел. Общий тип массива
может содержать любой Lisp объект. Другие типы массивов
специализируются для эффективности и могут содержать только
определённые типы Lisp объектов. Также существует возможность
того, что два массива, возможно с разным количеством измерений,
указывают на одно и то же подмножество объектов (если
изменить первый массив, изменится и второй). Это достигается
с помощью указания для одного массива быть связанным с
другим массивом. Одномерные массивы любого типа называются
векторами (vectors). Одномерные массивы букв называются
строки. Одномерные массивы битов (это целое число, которое
может содержать 0 или 1) называются битовыми векторами
(bit-vectors).
- Хеш-таблицы предоставляют эффективный способ связывания
любого Lisp объекта (ключа) с другим объектом (значением).
- Таблицы
символов Lisp парсера (readtables) используются для управления
парсером выражений read. Этот функционал предназначен для
создания макроридеров для ограниченного изменения синтаксиса
языка.
- Пакеты являются коллекциями символов и служат для разделения
их на пространства имён. Парсер распознает символы с помощью
поиска их имён в текущем пакете.
- Имена файлов (pathnames) хранят в себе путь к файлу в
кроссплатформенном виде. Они используются для взаимодействия
с внешней файловой системой.
- Потоки представляют источники данных, обычно строковых
символов или байтов. Они используются для ввода/вывода, а
также для внутренних нужд, например для парсинга строк.
- Состояния генератора случайных чисел (random-states) — это
структуры данных, используемые для хранения состояния
встроенного генератора случайных чисел (ГСЧ).
- Структуры — это определённые пользователем объекты, имеющие
именованные поля. defstruct используется для определения новых
типов структур. Некоторые реализации Common Lisp’а могут
внутренне предоставлять некоторые системные типы такие, как
bignums, таблицы символов Lisp парсера (readtables), потоки
(streams), хеш-таблицы (hash tables) и имена файлов (pathnames)
как структуры, но для пользователя это не имеет значения.
- Условия (conditions) — это объекты, используемые для управления
ходом выполнения программы с помощью сигналов и обработчиков
этих самых сигналов. В частности, ошибки сигнализируются с
помощью генерации условия, и эти ошибки могут быть обработаны
с помощью установленных для этих условий обработчиков.
- Классы определяют структуру и поведение других объектов,
являющихся экземплярами данных классов. Каждый объект
данных принадлежит некоторому классу.
- Методы —
это код, который оперирует аргументами, которые соответствуют
некоторому шаблону. Методы не являются функциями; они не
вызываются напрямую, а объединяются в обобщённые функции
(generic functions).
- Обобщённые функции — это функции, которые содержат,
кроме всего прочего, множество методов. При вызове generic
функция вызывает подмножество её методов. Подмножество
для выполнения выделяется с помощью определения классов
аргументов и выбора им соответствующих методов.
Эти категории не всегда взаимоисключаемы. Указанные отношения
между различными типами данных более детально описано в разделе 2.15.