Функциональность структур воплощена в макросе defstruct, который позволяет пользователю создавать и использовать сгруппированные типы данных с именованными элементами. Она похожа на функциональность «структур (structures)» в PL/I или «записей (records)» в Pascal’е.
В качестве примера, предположим, что вы пишете программу на Lisp’е, которая управляет космическими кораблями в двухмерном пространстве. Вам необходимо представить космический корабль как некоторого вида Lisp’овый объект. Интересующими свойствами корабля являются: его позиция (представленная как x и y координаты), скорость (представленная как отрезки по осям x и y) и масса.
Таким образом, корабль может быть представлен как запись структуры с пятью компонентами: позиция-x, позиция-y, скорость-x, скорость-y и масса. Эта структура может быть реализована как Lisp’овый объект несколькими способами. Она может быть списком из пяти элементов; позиция-x будет car элементом, позиция-y будет cadr, и так далее. Подобным образом структура может быть вектором из пяти элементов: позиция-x будет 0-ым элементом, позиция-y будет 1-ым, и так далее. Проблема данных представлений состоит в том, что компоненты занимают совершенно случайные позиции и их сложно запомнить. Кто-нибудь увидев где-то в коде строки (cadddr ship1) или (aref ship1 3), обнаружит сложность в определении того, что это производится доступ к компоненту скорости-y структуры ship1. Более того, если представление корабля должно быть изменено, то будет очень сложно найти все места в коде для изменения в соответствие с новым представлением (не все появления cadddr означают доступ к скорости-y корабля).
Лучше было бы, если бы записи структур имели имена. Можно было бы написать что-то вроде (ship-y-velocity ship1) вместо (cadddr ship1). Кроме того было бы неплохо иметь более информативную запись для создания структур, чем эта:
Несомненно, хочется, чтобы ship был новым типом данных, как и любой другой тип Lisp’овых данных, чтобы, например, осуществить проверку с помощью typep. defstruct предоставляет вам все, что необходимо.
defstruct является макросом, который определяет структуру. Например, для космического корабля, можно определить структуру так:
Запись декларирует, что каждый объект ship является объектом с пятью именованными компонентами. Вычисление этой формы делает несколько вещей.
устанавливает в ship2 свеже созданный объект ship. Можно указать первоначальные значения для компонентов структуры используя именованные параметры:
Форма создаёт новый корабль и инициализирует три его компонента. Эта функция называется функцией-конструктором, потому что создаёт новую структуру.
Данная запись изменяет позицию-x переменной ship2 в 100. Она работает, потому что defstruct ведёт себя так, будто создаёт соответствующие defsetf формы для функций доступа.
Этот простой пример отображает мощь и удобство defstruct для представления записей структур. defstruct имеет много других возможностей для специализированных целей.