Предыдущего описание defstruct достаточно для среднестатистического использования. Оставшуюся часть этой главы занимает описание более сложных возможностей функционала defstruct.
Данный раздел объясняет каждый параметр, который может быть использован в defstruct. Параметр для defstruct может быть или ключевым символом, или списком из ключевого символа и аргумента для него. (Следует отметить, что синтаксис для параметров defstruct отличается от синтаксиса пар, используемых для параметров слота. Никакая часть этих параметров не вычисляется.)
Аргумент :conc-name указывает альтернативный префикс. (Если в качестве разделителя используется дефис, он указывается как часть префикса.) Если в качестве аргумента указано nil, тогда префикс не устанавливается вообще. Тогда имена функций доступа совпадают с именами слотов, и это повод давать слотам информативные имена.
Следует отметить, что не зависимо от того, что указано в :conc-name, в функции-конструкторе используются ключевые символы, совпадающие с именами слотов без присоединяемого префикса. С другой стороны префикс используется в именах функций доступа. Например:
Этот параметр имеет более сложный синтаксис, описываемый в разделе 19.6.
Автоматически создаваемая функция копирования просто создаёт новую структуру и переносит все компоненты из структуры аргумента в свеже создаваемую структуру. Копирование самих компонентов структуры не производится. Соответствующие элементы старой и новой структуры равны eql между собой.
Теперь, предположим, вы хотите создать новую структуру для представления астронавта. Так как астронавт также человек, вы хотите, чтобы он также имел свойства имя, возраст и пол, и вы хотите чтобы Lisp’овые функции работали со структурами astronaut также как и с структурами person. Вы можете сделать это определив структуру astronaut с параметром :include, так:
Параметр :include заставляет структуру, будучи определённой, иметь те же слоты, что и включаемая в параметре структура. Это реализуется с помощью того, что функции доступа включаемой структуры будут также работать с определяемой структурой. Таким образом, в этом примере, astronaut будет иметь пять слотов: три определены в person и два в самом astronaut. Функции доступа, определённые с помощью структуры person, могут применяться к экземплярам структуры astronaut, и будут корректно работать. Более того, astronaut будет иметь свои функции доступа для компонентов унаследованных от структуры person. Следующий пример иллюстрирует то, как вы можете использовать структуры astronaut:
Различие между функциями доступа person-name и astro-name в том, что person-name может быть корректно применена к любому экземпляру person, включая astronaut, тогда как astro-name может работать только с astronaut. (Реализация может проверять или не проверять корректное использоваться таких функций доступа.)
В одной форме defstruct не может использовать более одного параметра :include. Аргумент для параметра :include является обязательным и должен быть именем определённой ранее структуры. Если структура, будучи определённой, не содержала параметра :type, тогда наследуемая структура также не должна содержать этот параметр. Если структура, будучи определённой, содержала параметр :type, тогда наследуемая структура должна содержать этот параметр с тем же типом.
Если параметр :type не указан, тогда имя структуры становиться именем типа данных. Более того, тип будет является подтипом типа структуры, от которой произошло наследование. В вышеприведённом примере, astronaut является подтипом person. Так,
но и указывает, что все операции над person будут также работать для astronaut.
Далее рассказывается чуть более сложные возможности параметра :include. Иногда, когда одна структура включает другую, необходимо, чтобы значения по-умолчанию или параметры слотов из родительской структуры при наследовании стали слегка другими. Новая структура может задать значения по-умолчанию или параметры для наследуемых слотов отличными от родительских, с помощью конструкции:
Каждая форма slot-description-j должна иметь имя slot-name или slot-keyword, такое же как в родительской структуре. Если slot-description-j не имеет формы инициализации default-init, тогда в новой структуре слот также не будет иметь первоначального значения. В противном случае его первоначальное значение будет заменено формой default-init из slot-description-j. Доступный для записи слот может быть переделан в слот только для чтения. Если слот только для чтения в родительской структуре, тогда он также должен быть только для чтения в дочерней. Если для слота указан тип, он должен быть таким же или подтипом в дочерней структуре. Если это строгий подтип, то реализация может проверять или не проверять ошибки несовпадения типов при присваивании значений слотам.
Например, если мы хотели бы определить astronaut так, чтобы по-умолчанию возрастом астронавта было 45 лет, то мы могли бы сказать:
Если параметры :print-function и :type не указаны, тогда функция вывода по-умолчанию выводит все слоты используя синтаксис #S (смотрите раздел 22.1.4).
Этот параметр заставляет использовать указанное представление и заставляет компоненты быть размещёнными в порядке, предусмотренном в defstruct форме, в соответствующие последовательные элементы указанного представления. Параметр также отключает возможность имени структуры стать именем типа. (смотрите раздел 19.7).
Обычно этот параметр не используется, и тогда структура представляется так, как предусмотрено в реализации.