1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Body/m_defstr.htm
2024-04-01 10:24:07 +02:00

525 lines
62 KiB
HTML

<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
<HTML>
<HEAD>
<TITLE>CLHS: Macro DEFSTRUCT</TITLE>
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
<LINK REL=TOP HREF="../Front/index.htm">
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
<LINK REL=PREV HREF="c_struct.htm">
<LINK REL=UP HREF="c_struct.htm">
<LINK REL=NEXT HREF="f_cp_stu.htm">
</HEAD>
<BODY>
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="c_struct.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="c_struct.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="f_cp_stu.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<A NAME="defstruct"><I>Macro</I> <B>DEFSTRUCT</B></A> <P>
<P><B>Syntax:</B><P>
<P>
<B>defstruct</B> <I>name-and-options [documentation] {<I>slot-description</I>}<B>*</B></I><P> =&gt; <I>structure-name</I><P>
<P>
<PRE>
name-and-options::= structure-name | (structure-name [[options]])
</PRE>
<PRE>
options::= conc-name-option |
{constructor-option}* |
copier-option |
include-option |
initial-offset-option |
named-option |
predicate-option |
printer-option |
type-option
</PRE>
<PRE>
conc-name-option::= :conc-name | (:conc-name) | (:conc-name conc-name)
</PRE>
<PRE>
constructor-option::= :constructor |
(:constructor) |
(:constructor constructor-name) |
(:constructor constructor-name constructor-arglist)
</PRE>
<PRE>
copier-option::= :copier | (:copier) | (:copier copier-name)
</PRE>
<PRE>
predicate-option::= :predicate | (:predicate) | (:predicate predicate-name)
</PRE>
<PRE>
include-option::= (:include included-structure-name {slot-description}*)
</PRE>
<PRE>
printer-option::= print-object-option | print-function-option
</PRE>
<PRE>
print-object-option::= (:print-object printer-name) | (:print-object)
</PRE>
<PRE>
print-function-option::= (:print-function printer-name) | (:print-function)
</PRE>
<PRE>
type-option::= (:type type)
</PRE>
<PRE>
named-option::= :named
</PRE>
<PRE>
initial-offset-option::= (:initial-offset initial-offset)
</PRE>
<PRE>
slot-description::= slot-name |
(slot-name [slot-initform [[slot-option]]])
</PRE>
<PRE>
slot-option::= :type slot-type |
:read-only slot-read-only-p
</PRE>
<P>
<P><B>Arguments and Values:</B><P>
<P>
<I>conc-name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#string_designator"><I>string designator</I></A>. <P>
<I>constructor-arglist</I>---a <A REL=DEFINITION HREF="26_glo_b.htm#boa_lambda_list"><I>boa lambda list</I></A>. <P>
<I>constructor-name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
<I>copier-name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
<I>included-structure-name</I>---an already-defined <A REL=DEFINITION HREF="26_glo_s.htm#structure_name"><I>structure name</I></A>. Note that a <A REL=DEFINITION HREF="26_glo_d.htm#derived_type"><I>derived type</I></A> is not permissible, even if it would expand into a <A REL=DEFINITION HREF="26_glo_s.htm#structure_name"><I>structure name</I></A>. <P>
<I>initial-offset</I>---a non-negative <A REL=DEFINITION HREF="26_glo_i.htm#integer"><I>integer</I></A>. <P>
<I>predicate-name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
<I>printer-name</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#function_name"><I>function name</I></A> or a <A REL=DEFINITION HREF="26_glo_l.htm#lambda_expression"><I>lambda expression</I></A>. <P>
<I>slot-name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
<I>slot-initform</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. <P>
<I>slot-read-only-p</I>---a <A REL=DEFINITION HREF="26_glo_g.htm#generalized_boolean"><I>generalized boolean</I></A>. <P>
<I>structure-name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
<I>type</I>---one of the <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifiers</I></A> <A REL=DEFINITION HREF="t_list.htm#list"><B>list</B></A>, <A REL=DEFINITION HREF="t_vector.htm#vector"><B>vector</B></A>, or <TT>(vector </TT><I>size</I><TT>)</TT>, or some other <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A> defined by the <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementation</I></A> to be appropriate. <P>
<I>documentation</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#string"><I>string</I></A>; not evaluated. <P>
<P><B>Description:</B><P>
<P>
<A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> defines a structured <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A>, named <I>structure-type</I>, with named slots as specified by the <I>slot-options</I>. <P>
<A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> defines <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>readers</I></A> for the slots and arranges for <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A> to work properly on such <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions. Also, unless overridden, it defines a predicate named <TT></TT><I>name</I><TT>-p</TT>, defines a constructor function named <TT>make-</TT><I>constructor-name</I><TT></TT>, and defines a copier function named <TT>copy-</TT><I>constructor-name</I><TT></TT>. All names of automatically created functions might automatically be declared <A REL=DEFINITION HREF="d_inline.htm#inline"><B>inline</B></A> (at the discretion of the <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementation</I></A>). <P>
If <I>documentation</I> is supplied, it is attached to <I>structure-name</I> as a <A REL=DEFINITION HREF="26_glo_d.htm#documentation_string"><I>documentation string</I></A> of kind <A REL=DEFINITION HREF="f_docume.htm#structure"><B>structure</B></A>, and unless <TT>:type</TT> is used, the <I>documentation</I> is also attached to <I>structure-name</I> as a <A REL=DEFINITION HREF="26_glo_d.htm#documentation_string"><I>documentation string</I></A> of kind <A REL=DEFINITION HREF="a_type.htm#type"><B>type</B></A> and as a <A REL=DEFINITION HREF="26_glo_d.htm#documentation_string"><I>documentation string</I></A> to the <A REL=DEFINITION HREF="26_glo_c.htm#class"><I>class</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A> for the <A REL=DEFINITION HREF="26_glo_c.htm#class"><I>class</I></A> named <I>structure-name</I>. <P>
<A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> defines a constructor function that is used to create instances of the structure created by <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A>. The default name is <TT>make-</TT><I>structure-name</I><TT></TT>. A different name can be supplied by giving the name as the argument to the <I>constructor</I> option. <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> indicates that no constructor function will be created. <P>
After a new structure type has been defined, instances of that type normally can be created by using the constructor function for the type. A call to a constructor function is of the following form: <P>
<PRE>
(constructor-function-name
slot-keyword-1 form-1
slot-keyword-2 form-2
...)
</PRE>
</TT> <P>
The arguments to the constructor function are all keyword arguments. Each slot keyword argument must be a keyword whose name corresponds to the name of a structure slot. All the <I>keywords</I> and <I>forms</I> are evaluated. If a slot is not initialized in this way, it is initialized by evaluating <I>slot-initform</I> in the slot description at the time the constructor function is called. If no <I>slot-initform</I> is supplied, the consequences are undefined if an attempt is later made to read the slot's value before a value is explicitly assigned. <P>
Each <I>slot-initform</I> supplied for a <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> component, when used by the constructor function for an otherwise unsupplied component, is re-evaluated on every call to the constructor function. The <I>slot-initform</I> is not evaluated unless it is needed in the creation of a particular structure instance. If it is never needed, there can be no type-mismatch error, even if the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> of the slot is specified; no warning should be issued in this case. For example, in the following sequence, only the last call is an error. <P>
<PRE>
(defstruct person (name 007 :type string))
(make-person :name &quot;James&quot;)
(make-person)
</PRE>
</TT> <P>
It is as if the <I>slot-initforms</I> were used as <A REL=DEFINITION HREF="26_glo_i.htm#initialization_form"><I>initialization forms</I></A> for the <A REL=DEFINITION HREF="26_glo_k.htm#keyword_parameter"><I>keyword parameters</I></A> of the constructor function. <P>
The <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbols</I></A> which name the slots must not be used by the <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementation</I></A> as the <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>names</I></A> for the <A REL=DEFINITION HREF="26_glo_l.htm#lambda_variable"><I>lambda variables</I></A> in the constructor function, since one or more of those <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbols</I></A> might have been proclaimed <A REL=DEFINITION HREF="d_specia.htm#special"><B>special</B></A> or might be defined as the name of a <A REL=DEFINITION HREF="26_glo_c.htm#constant_variable"><I>constant variable</I></A>. The slot default init forms are evaluated in the <A REL=DEFINITION HREF="26_glo_l.htm#lexical_environment"><I>lexical environment</I></A> in which the <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> form itself appears and in the <A REL=DEFINITION HREF="26_glo_d.htm#dynamic_environment"><I>dynamic environment</I></A> in which the call to the constructor function appears. <P>
For example, if the form <TT>(gensym)</TT> were used as an initialization form, either in the constructor-function call or as the default initialization form in <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A>, then every call to the constructor function would call <A REL=DEFINITION HREF="f_gensym.htm#gensym"><B>gensym</B></A> once to generate a new <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
Each <I>slot-description</I> in <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> can specify zero or more <I>slot-options</I>. A <I>slot-option</I> consists of a pair of a keyword and a value (which is not a form to be evaluated, but the value itself). For example: <P>
<PRE>
(defstruct ship
(x-position 0.0 :type short-float)
(y-position 0.0 :type short-float)
(x-velocity 0.0 :type short-float)
(y-velocity 0.0 :type short-float)
(mass *default-ship-mass* :type short-float :read-only t))
</PRE>
</TT> This specifies that each slot always contains a <A REL=DEFINITION HREF="26_glo_s.htm#short_float"><I>short float</I></A>, and that the last slot cannot be altered once a ship is constructed. <P>
The available slot-options are: <P><DL><DT><TT>:type </TT><I>type</I><TT></TT> <P><DD>
This specifies that the contents of the slot is always of type <I>type</I>. This is entirely analogous to the declaration of a variable or function; it effectively declares the result type of the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function. It is <A REL=DEFINITION HREF="26_glo_i.htm#implementation-dependent"><I>implementation-dependent</I></A> whether the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> is checked when initializing a slot or when assigning to it. <I>Type</I> is not evaluated; it must be a valid <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A>. <P>
<DT><TT>:read-only </TT><I>x</I><TT></TT> <P><DD>
When <I>x</I> is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A>, this specifies that this slot cannot be altered; it will always contain the value supplied at construction time. <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A> will not accept the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function for this slot. If <I>x</I> is <A REL=DEFINITION HREF="26_glo_f.htm#false"><I>false</I></A>, this slot-option has no effect. <I>X</I> is not evaluated. <P>
When this option is <A REL=DEFINITION HREF="26_glo_f.htm#false"><I>false</I></A> or unsupplied, it is <A REL=DEFINITION HREF="26_glo_i.htm#implementation-dependent"><I>implementation-dependent</I></A> whether the ability to <A REL=DEFINITION HREF="26_glo_w.htm#write"><I>write</I></A> the slot is implemented by a <A REL=DEFINITION HREF="26_glo_s.htm#setf_function"><I>setf function</I></A> or a <A REL=DEFINITION HREF="26_glo_s.htm#setf_expander"><I>setf expander</I></A>. <P>
<P></DL><P>
The following keyword options are available for use with <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A>. A <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> option can be either a keyword or a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of a keyword and arguments for that keyword; specifying the keyword by itself is equivalent to specifying a list consisting of the keyword and no arguments. The syntax for <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> options differs from the pair syntax used for slot-options. No part of any of these options is evaluated. <P><DL><P>
<DT><TT>:conc-name</TT> <P><DD>
This provides for automatic prefixing of names of <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> (or <A REL=DEFINITION HREF="26_glo_a.htm#access"><I>access</I></A>) functions. The default behavior is to begin the names of all the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions of a structure with the name of the structure followed by a hyphen. <P>
<TT>:conc-name</TT> supplies an alternate prefix to be used. If a hyphen is to be used as a separator, it must be supplied as part of the prefix. If <TT>:conc-name</TT> is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> or no argument is supplied, then no prefix is used; then the names of the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions are the same as the slot names. If a <A REL=DEFINITION HREF="26_glo_n.htm#non-nil"><I>non-nil</I></A> prefix is given, the name of the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> for each slot is constructed by concatenating that prefix and the name of the slot, and interning the resulting <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> in the <A REL=DEFINITION HREF="26_glo_p.htm#package"><I>package</I></A> that is current at the time the <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> form is expanded. <P>
Note that no matter what is supplied for <TT>:conc-name</TT>, slot keywords that match the slot names with no prefix attached are used with a constructor function. The <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function name is used in conjunction with <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A>. Here is an example: <P>
<PRE>
(defstruct (door (:conc-name dr-)) knob-color width material) =&gt; DOOR
(setq my-door (make-door :knob-color 'red :width 5.0))
=&gt; #S(DOOR :KNOB-COLOR RED :WIDTH 5.0 :MATERIAL NIL)
(dr-width my-door) =&gt; 5.0
(setf (dr-width my-door) 43.7) =&gt; 43.7
(dr-width my-door) =&gt; 43.7
</PRE>
</TT> <P>
Whether or not the <TT>:conc-name</TT> option is explicitly supplied, the following rule governs name conflicts of generated <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> (or <A REL=DEFINITION HREF="26_glo_a.htm#accessor"><I>accessor</I></A>) names: For any <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> S1 having a <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function named R for a slot named X1 that is inherited by another <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> S2 that would have a <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function with the same name R for a slot named X2, no definition for R is generated by the definition of S2; instead, the definition of R is inherited from the definition of S1. (In such a case, if X1 and X2 are different slots, the <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementation</I></A> might signal a style warning.) <P>
<DT><TT>:constructor</TT> <P><DD>
This option takes zero, one, or two arguments. If at least one argument is supplied and the first argument is not <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>, then that argument is a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> which specifies the name of the constructor function. If the argument is not supplied (or if the option itself is not supplied), the name of the constructor is produced by concatenating the string <TT>&quot;MAKE-&quot;</TT> and the name of the structure, interning the name in whatever <A REL=DEFINITION HREF="26_glo_p.htm#package"><I>package</I></A> is current at the time <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> is expanded. If the argument is provided and is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>, no constructor function is defined. <P>
If <TT>:constructor</TT> is given as <TT>(:constructor </TT><I>name</I><TT> </TT><I>arglist</I><TT>)</TT>, then instead of making a keyword driven constructor function, <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> defines a ``positional'' constructor function, taking arguments whose meaning is determined by the argument's position and possibly by keywords. <I>Arglist</I> is used to describe what the arguments to the constructor will be. In the simplest case something like <TT>(:constructor make-foo (a b c))</TT> defines <TT>make-foo</TT> to be a three-argument constructor function whose arguments are used to initialize the slots named <TT>a</TT>, <TT>b</TT>, and <TT>c</TT>. <P>
Because a constructor of this type operates ``By Order of Arguments,'' it is sometimes known as a ``boa constructor.'' <P>
For information on how the <I>arglist</I> for a ``boa constructor'' is processed, see <A REL=CHILD HREF="03_df.htm">Section 3.4.6 (Boa Lambda Lists)</A>. <P>
It is permissible to use the <TT>:constructor</TT> option more than once, so that you can define several different constructor functions, each taking different parameters. <P>
<P>
<A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> creates the default-named keyword constructor function only if no explicit <TT>:constructor</TT> options are specified, or if the <TT>:constructor</TT> option is specified without a <I>name</I> argument. <P>
<TT>(:constructor nil)</TT> is meaningful only when there are no other <TT>:constructor</TT> options specified. It prevents <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> from generating any constructors at all. <P>
Otherwise, <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> creates a constructor function corresponding to each supplied <TT>:constructor</TT> option. It is permissible to specify multiple keyword constructor functions as well as multiple ``boa constructors''. <P>
<DT><TT>:copier</TT> <P><DD>
This option takes one argument, a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>, which specifies the name of the copier function. If the argument is not provided or if the option itself is not provided, the name of the copier is produced by concatenating the string <TT>&quot;COPY-&quot;</TT> and the name of the structure, interning the name in whatever <A REL=DEFINITION HREF="26_glo_p.htm#package"><I>package</I></A> is current at the time <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> is expanded. If the argument is provided and is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>, no copier function is defined. <P>
The automatically defined copier function is a function of one <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>argument</I></A>, which must be of the structure type being defined. The copier function creates a <A REL=DEFINITION HREF="26_glo_f.htm#fresh"><I>fresh</I></A> structure that has the same <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> as its <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>argument</I></A>, and that has the <A REL=DEFINITION HREF="26_glo_s.htm#same"><I>same</I></A> component values as the original structure; that is, the component values are not copied recursively. If the <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> <TT>:type</TT> option was not used, the following equivalence applies: <P>
<PRE>
(copier-name x) = (copy-structure (the structure-name x))
</PRE>
</TT> <P>
<DT><TT>:include</TT> <P><DD>
This option is used for building a new structure definition as an extension of another structure definition. For example: <P>
<PRE>
(defstruct person name age sex)
</PRE>
</TT> To make a new structure to represent an astronaut that has the attributes of name, age, and sex, and <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>functions</I></A> that operate on <TT>person</TT> structures, <TT>astronaut</TT> is defined with <TT>:include</TT> as follows: <P>
<PRE>
(defstruct (astronaut (:include person)
(:conc-name astro-))
helmet-size
(favorite-beverage 'tang))
</PRE>
</TT> <P>
<TT>:include</TT> causes the structure being defined to have the same slots as the included structure. This is done in such a way that the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions for the included structure also work on the structure being defined. In this example, an <TT>astronaut</TT> therefore has five slots: the three defined in <TT>person</TT> and the two defined in <TT>astronaut</TT> itself. The <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions defined by the <TT>person</TT> structure can be applied to instances of the <TT>astronaut</TT> structure, and they work correctly. Moreover, <TT>astronaut</TT> has its own <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions for components defined by the <TT>person</TT> structure. The following examples illustrate the use of <TT>astronaut</TT> structures: <P>
<PRE>
(setq x (make-astronaut :name 'buzz
:age 45.
:sex t
:helmet-size 17.5))
(person-name x) =&gt; BUZZ
(astro-name x) =&gt; BUZZ
(astro-favorite-beverage x) =&gt; TANG
</PRE>
</TT>
<PRE>
(reduce #'+ astros :key #'person-age) ; obtains the total of the ages
; of the possibly empty
; sequence of astros
</PRE>
</TT> The difference between the <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions <TT>person-name</TT> and <TT>astro-name</TT> is that <TT>person-name</TT> can be correctly applied to any <TT>person</TT>, including an <TT>astronaut</TT>, while <TT>astro-name</TT> can be correctly applied only to an <TT>astronaut</TT>. An implementation might check for incorrect use of <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions. <P>
At most one <TT>:include</TT> can be supplied in a single <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A>. The argument to <TT>:include</TT> is required and must be the name of some previously defined structure. If the structure being defined has no <TT>:type</TT> option, then the included structure must also have had no <TT>:type</TT> option supplied for it. If the structure being defined has a <TT>:type</TT> option, then the included structure must have been declared with a <TT>:type</TT> option specifying the same representation <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A>. <P>
If no <TT>:type</TT> option is involved, then the structure name of the including structure definition becomes the name of a <A REL=DEFINITION HREF="26_glo_d.htm#data_type"><I>data type</I></A>, and therefore a valid <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A> recognizable by <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A>; it becomes a <A REL=DEFINITION HREF="26_glo_s.htm#subtype"><I>subtype</I></A> of the included structure. In the above example, <TT>astronaut</TT> is a <A REL=DEFINITION HREF="26_glo_s.htm#subtype"><I>subtype</I></A> of <TT>person</TT>; hence <P>
<PRE>
(typep (make-astronaut) 'person) =&gt; <A REL=DEFINITION HREF="26_glo_t.htm#true">true</A>
</PRE>
</TT> indicating that all operations on persons also work on astronauts. <P>
The structure using <TT>:include</TT> can specify default values or slot-options for the included slots different from those the included structure specifies, by giving the <TT>:include</TT> option as: <P>
<PRE>
(:include included-structure-name slot-description*)
</PRE>
</TT> Each <I>slot-description</I> must have a <I>slot-name</I> that is the same as that of some slot in the included structure. If a <I>slot-description</I> has no <I>slot-initform</I>, then in the new structure the slot has no initial value. Otherwise its initial value form is replaced by the <I>slot-initform</I> in the <I>slot-description</I>. A normally writable slot can be made read-only. If a slot is read-only in the included structure, then it must also be so in the including structure. If a <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> is supplied for a slot, it must be a <A REL=DEFINITION HREF="26_glo_s.htm#subtype"><I>subtype</I></A> of the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> specified in the included structure. <P>
For example, if the default age for an astronaut is <TT>45</TT>, then <P>
<PRE>
(defstruct (astronaut (:include person (age 45)))
helmet-size
(favorite-beverage 'tang))
</PRE>
</TT> <P>
If <TT>:include</TT> is used with the <TT>:type</TT> option, then the effect is first to skip over as many representation elements as needed to represent the included structure, then to skip over any additional elements supplied by the <TT>:initial-offset</TT> option, and then to begin allocation of elements from that point. For example: <P>
<PRE>
(defstruct (binop (:type list) :named (:initial-offset 2))
(operator '? :type symbol)
operand-1
operand-2) =&gt; BINOP
(defstruct (annotated-binop (:type list)
(:initial-offset 3)
(:include binop))
commutative associative identity) =&gt; ANNOTATED-BINOP
(make-annotated-binop :operator '*
:operand-1 'x
:operand-2 5
:commutative t
:associative t
:identity 1)
=&gt; (NIL NIL BINOP * X 5 NIL NIL NIL T T 1)
</PRE>
</TT> The first two <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> elements stem from the <TT>:initial-offset</TT> of <TT>2</TT> in the definition of <TT>binop</TT>. The next four elements contain the structure name and three slots for <TT>binop</TT>. The next three <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> elements stem from the <TT>:initial-offset</TT> of <TT>3</TT> in the definition of <TT>annotated-binop</TT>. The last three list elements contain the additional slots for an <TT>annotated-binop</TT>. <P>
<DT><TT>:initial-offset</TT> <P><DD>
<TT>:initial-offset</TT> instructs <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> to skip over a certain number of slots before it starts allocating the slots described in the body. This option's argument is the number of slots <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> should skip. <TT>:initial-offset</TT> can be used only if <TT>:type</TT> is also supplied. <P>
<TT>:initial-offset</TT> allows slots to be allocated beginning at a representational element other than the first. For example, the form <P>
<PRE>
(defstruct (binop (:type list) (:initial-offset 2))
(operator '? :type symbol)
operand-1
operand-2) =&gt; BINOP
</PRE>
</TT> would result in the following behavior for <TT>make-binop</TT>: <P>
<PRE>
(make-binop :operator '+ :operand-1 'x :operand-2 5)
=&gt; (NIL NIL + X 5)
(make-binop :operand-2 4 :operator '*)
=&gt; (NIL NIL * NIL 4)
</PRE>
</TT> The selector functions <TT>binop-operator</TT>, <TT>binop-operand-1</TT>, and <TT>binop-operand-2</TT> would be essentially equivalent to <A REL=DEFINITION HREF="f_firstc.htm#third"><B>third</B></A>, <A REL=DEFINITION HREF="f_firstc.htm#fourth"><B>fourth</B></A>, and <A REL=DEFINITION HREF="f_firstc.htm#fifth"><B>fifth</B></A>, respectively. Similarly, the form <P>
<PRE>
(defstruct (binop (:type list) :named (:initial-offset 2))
(operator '? :type symbol)
operand-1
operand-2) =&gt; BINOP
</PRE>
</TT> would result in the following behavior for <TT>make-binop</TT>: <P>
<PRE>
(make-binop :operator '+ :operand-1 'x :operand-2 5) =&gt; (NIL NIL BINOP + X 5)
(make-binop :operand-2 4 :operator '*) =&gt; (NIL NIL BINOP * NIL 4)
</PRE>
</TT> <P>
The first two <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> elements stem from the <TT>:initial-offset</TT> of <TT>2</TT> in the definition of <TT>binop</TT>. The next four elements contain the structure name and three slots for <TT>binop</TT>. <P>
<DT><TT>:named</TT> <P><DD>
<TT>:named</TT> specifies that the structure is named. If no <TT>:type</TT> is supplied, then the structure is always named. <P>
For example: <P>
<PRE>
(defstruct (binop (:type list))
(operator '? :type symbol)
operand-1
operand-2) =&gt; BINOP
</PRE>
</TT> This defines a constructor function <TT>make-binop</TT> and three selector functions, namely <TT>binop-operator</TT>, <TT>binop-operand-1</TT>, and <TT>binop-operand-2</TT>. (It does not, however, define a predicate <TT>binop-p</TT>, for reasons explained below.) <P>
The effect of <TT>make-binop</TT> is simply to construct a list of length three: <P>
<PRE>
(make-binop :operator '+ :operand-1 'x :operand-2 5) =&gt; (+ X 5)
(make-binop :operand-2 4 :operator '*) =&gt; (* NIL 4)
</PRE>
</TT> It is just like the function <TT>list</TT> except that it takes keyword arguments and performs slot defaulting appropriate to the <TT>binop</TT> conceptual data type. Similarly, the selector functions <TT>binop-operator</TT>, <TT>binop-operand-1</TT>, and <TT>binop-operand-2</TT> are essentially equivalent to <A REL=DEFINITION HREF="f_car_c.htm#car"><B>car</B></A>, <A REL=DEFINITION HREF="f_car_c.htm#cadr"><B>cadr</B></A>, and <A REL=DEFINITION HREF="f_car_c.htm#caddr"><B>caddr</B></A>, respectively. They might not be completely equivalent because, for example, an implementation would be justified in adding error-checking code to ensure that the argument to each selector function is a length-3 list. <P>
<TT>binop</TT> is a conceptual data type in that it is not made a part of the Common Lisp type system. <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A> does not recognize <TT>binop</TT> as a <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A>, and <A REL=DEFINITION HREF="f_tp_of.htm#type-of"><B>type-of</B></A> returns <TT>list</TT> when given a <TT>binop</TT> structure. There is no way to distinguish a data structure constructed by <TT>make-binop</TT> from any other <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> that happens to have the correct structure. <P>
There is not any way to recover the structure name <TT>binop</TT> from a structure created by <TT>make-binop</TT>. This can only be done if the structure is named. A named structure has the property that, given an instance of the structure, the structure name (that names the type) can be reliably recovered. For structures defined with no <TT>:type</TT> option, the structure name actually becomes part of the Common Lisp data-type system. <A REL=DEFINITION HREF="f_tp_of.htm#type-of"><B>type-of</B></A>, when applied to such a structure, returns the structure name as the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> of the <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A>; <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A> recognizes the structure name as a valid <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A>. <P>
For structures defined with a <TT>:type</TT> option, <A REL=DEFINITION HREF="f_tp_of.htm#type-of"><B>type-of</B></A> returns a <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A> such as <TT>list</TT> or <TT>(vector t)</TT>, depending on the type supplied to the <TT>:type</TT> option. The structure name does not become a valid <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A>. However, if the <TT>:named</TT> option is also supplied, then the first component of the structure (as created by a <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> constructor function) always contains the structure name. This allows the structure name to be recovered from an instance of the structure and allows a reasonable predicate for the conceptual type to be defined: the automatically defined <I>name-p</I> predicate for the structure operates by first checking that its argument is of the proper type (<A REL=DEFINITION HREF="t_list.htm#list"><B>list</B></A>, <TT>(vector t)</TT>, or whatever) and then checking whether the first component contains the appropriate type name. <P>
Consider the <TT>binop</TT> example shown above, modified only to include the <TT>:named</TT> option: <P>
<PRE>
(defstruct (binop (:type list) :named)
(operator '? :type symbol)
operand-1
operand-2) =&gt; BINOP
</PRE>
</TT> As before, this defines a constructor function <TT>make-binop</TT> and three selector functions <TT>binop-operator</TT>, <TT>binop-operand-1</TT>, and <TT>binop-operand-2</TT>. It also defines a predicate <TT>binop-p</TT>. The effect of <TT>make-binop</TT> is now to construct a list of length four: <P>
<PRE>
(make-binop :operator '+ :operand-1 'x :operand-2 5) =&gt; (BINOP + X 5)
(make-binop :operand-2 4 :operator '*) =&gt; (BINOP * NIL 4)
</PRE>
</TT> The structure has the same layout as before except that the structure name <TT>binop</TT> is included as the first list element. The selector functions <TT>binop-operator</TT>, <TT>binop-operand-1</TT>, and <TT>binop-operand-2</TT> are essentially equivalent to <A REL=DEFINITION HREF="f_car_c.htm#cadr"><B>cadr</B></A>, <A REL=DEFINITION HREF="f_car_c.htm#caddr"><B>caddr</B></A>, and <A REL=DEFINITION HREF="f_car_c.htm#cadddr"><B>cadddr</B></A>, respectively. The predicate <TT>binop-p</TT> is more or less equivalent to this definition: <P>
<PRE>
(defun binop-p (x)
(and (consp x) (eq (car x) 'binop))) =&gt; BINOP-P
</PRE>
</TT> The name <TT>binop</TT> is still not a valid <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A> recognizable to <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A>, but at least there is a way of distinguishing <TT>binop</TT> structures from other similarly defined structures. <P>
<DT><TT>:predicate</TT> <P><DD>
This option takes one argument, which specifies the name of the type predicate. If the argument is not supplied or if the option itself is not supplied, the name of the predicate is made by concatenating the name of the structure to the string <TT>&quot;-P&quot;</TT>, interning the name in whatever <A REL=DEFINITION HREF="26_glo_p.htm#package"><I>package</I></A> is current at the time <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> is expanded. If the argument is provided and is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>, no predicate is defined. A predicate can be defined only if the structure is named; if <TT>:type</TT> is supplied and <TT>:named</TT> is not supplied, then <TT>:predicate</TT> must either be unsupplied or have the value <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>. <P>
<DT><TT>:print-function</TT>, <TT>:print-object</TT> <P><DD>
The <TT>:print-function</TT> and <TT>:print-object</TT> options specify that a <A REL=DEFINITION HREF="f_pr_obj.htm#print-object"><B>print-object</B></A> <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>method</I></A> for <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structures</I></A> of type <I>structure-name</I> should be generated. These options are not synonyms, but do perform a similar service; the choice of which option (<TT>:print-function</TT> or <TT>:print-object</TT>) is used affects how the function named <I>printer-name</I> is called. Only one of these options may be used, and these options may be used only if <TT>:type</TT> is not supplied. <P>
If the <TT>:print-function</TT> option is used, then when a structure of type <I>structure-name</I> is to be printed, the designated printer function is called on three <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A>: <P>
<P><UL><P>
<LI> the structure to be printed (a <A REL=DEFINITION HREF="26_glo_g.htm#generalized_instance"><I>generalized instance</I></A> of <I>structure-name</I>). <P>
<LI> a <A REL=DEFINITION HREF="26_glo_s.htm#stream"><I>stream</I></A> to print to. <P>
<LI> an <A REL=DEFINITION HREF="26_glo_i.htm#integer"><I>integer</I></A> indicating the current depth. The magnitude of this integer may vary between <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementations</I></A>; however, it can reliably be compared against <A REL=DEFINITION HREF="v_pr_lev.htm#STprint-levelST"><B>*print-level*</B></A> to determine whether depth abbreviation is appropriate. <P>
<P></UL><P>
Specifying <TT>(:print-function </TT><I>printer-name</I><TT>)</TT> is approximately equivalent to specifying: <P>
<PRE>
(defmethod print-object ((object structure-name) stream)
(funcall (function printer-name) object stream &lt;&lt;current-print-depth&gt;&gt;))
</PRE>
</TT> <P>
where the &lt;&lt;<I>current-print-depth</I>&gt;&gt; represents the printer's belief of how deep it is currently printing. It is <A REL=DEFINITION HREF="26_glo_i.htm#implementation-dependent"><I>implementation-dependent</I></A> whether &lt;&lt;<I>current-print-depth</I>&gt;&gt; is always 0 and <I>*print-level*</I>, if <A REL=DEFINITION HREF="26_glo_n.htm#non-nil"><I>non-nil</I></A>, is re-bound to successively smaller values as printing descends recursively, or whether <I>current-print-depth</I> varies in value as printing descends recursively and <I>*print-level*</I> remains constant during the same traversal. <P>
If the <TT>:print-object</TT> option is used, then when a structure of type <I>structure-name</I> is to be printed, the designated printer function is called on two arguments: <P>
<P><UL><P>
<LI> the structure to be printed. <P>
<LI> the stream to print to. <P>
<P></UL><P>
Specifying <TT>(:print-object </TT><I>printer-name</I><TT>)</TT> is equivalent to specifying: <P>
<PRE>
(defmethod print-object ((object structure-name) stream)
(funcall (function printer-name) object stream))
</PRE>
</TT> <P>
If no <TT>:type</TT> option is supplied, and if either a <TT>:print-function</TT> or a <TT>:print-object</TT> option is supplied, and if no <I>printer-name</I> is supplied, then a <A REL=DEFINITION HREF="f_pr_obj.htm#print-object"><B>print-object</B></A> <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>method</I></A> <A REL=DEFINITION HREF="26_glo_s.htm#specialized"><I>specialized</I></A> for <I>structure-name</I> is generated that calls a function that implements the default printing behavior for structures using <TT>#S</TT> notation; see <A REL=CHILD HREF="22_acl.htm">Section 22.1.3.12 (Printing Structures)</A>. <P>
If neither a <TT>:print-function</TT> nor a <TT>:print-object</TT> option is supplied, then <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> does not generate a <A REL=DEFINITION HREF="f_pr_obj.htm#print-object"><B>print-object</B></A> <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>method</I></A> <A REL=DEFINITION HREF="26_glo_s.htm#specialized"><I>specialized</I></A> for <I>structure-name</I> and some default behavior is inherited either from a structure named in an <TT>:include</TT> option or from the default behavior for printing structures; see the <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> <A REL=DEFINITION HREF="f_pr_obj.htm#print-object"><B>print-object</B></A> and <A REL=CHILD HREF="22_acl.htm">Section 22.1.3.12 (Printing Structures)</A>. <P>
When <A REL=DEFINITION HREF="v_pr_cir.htm#STprint-circleST"><B>*print-circle*</B></A> is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A>, a user-defined print function can print <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>objects</I></A> to the supplied <A REL=DEFINITION HREF="26_glo_s.htm#stream"><I>stream</I></A> using <A REL=DEFINITION HREF="f_wr_pr.htm#write"><B>write</B></A>, <A REL=DEFINITION HREF="f_wr_pr.htm#prin1"><B>prin1</B></A>, <A REL=DEFINITION HREF="f_wr_pr.htm#princ"><B>princ</B></A>, or <A REL=DEFINITION HREF="f_format.htm#format"><B>format</B></A> and expect circularities to be detected and printed using the <TT>#</TT><I>n</I><TT>#</TT> syntax. This applies to <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>methods</I></A> on <A REL=DEFINITION HREF="f_pr_obj.htm#print-object"><B>print-object</B></A> in addition to <TT>:print-function</TT> options. If a user-defined print function prints to a <A REL=DEFINITION HREF="26_glo_s.htm#stream"><I>stream</I></A> other than the one that was supplied, then circularity detection starts over for that <A REL=DEFINITION HREF="26_glo_s.htm#stream"><I>stream</I></A>. See the <A REL=DEFINITION HREF="26_glo_v.htm#variable"><I>variable</I></A> <A REL=DEFINITION HREF="v_pr_cir.htm#STprint-circleST"><B>*print-circle*</B></A>. <P>
<P>
<DT><TT>:type</TT> <P><DD>
<TT>:type</TT> explicitly specifies the representation to be used for the structure. Its argument must be one of these <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>types</I></A>: <P>
<P><DL><DT><A REL=DEFINITION HREF="t_vector.htm#vector"><B>vector</B></A> <P><DD>
This produces the same result as specifying <TT>(vector t)</TT>. The structure is represented as a general <A REL=DEFINITION HREF="26_glo_v.htm#vector"><I>vector</I></A>, storing components as vector elements. The first component is vector element 1 if the structure is <TT>:named</TT>, and element 0 otherwise. <P>
<DT><TT>(vector </TT><I>element-type</I><TT>)</TT> <P><DD>
The structure is represented as a (possibly specialized) <A REL=DEFINITION HREF="26_glo_v.htm#vector"><I>vector</I></A>, storing components as vector elements. Every component must be of a <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> that can be stored in a <A REL=DEFINITION HREF="26_glo_v.htm#vector"><I>vector</I></A> of the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> specified. The first component is vector element 1 if the structure is <TT>:named</TT>, and element 0 otherwise. The structure can be <TT>:named</TT> only if the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="t_symbol.htm#symbol"><B>symbol</B></A> is a <A REL=DEFINITION HREF="26_glo_s.htm#subtype"><I>subtype</I></A> of the supplied <I>element-type</I>. <P>
<DT><A REL=DEFINITION HREF="t_list.htm#list"><B>list</B></A> <P><DD>
The structure is represented as a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A>. The first component is the <A REL=DEFINITION HREF="26_glo_c.htm#cadr"><I>cadr</I></A> if the structure is <TT>:named</TT>, and the <A REL=DEFINITION HREF="26_glo_c.htm#car"><I>car</I></A> if it is not <TT>:named</TT>. <P></DL><P>
Specifying this option has the effect of forcing a specific representation and of forcing the components to be stored in the order specified in <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> in corresponding successive elements of the specified representation. It also prevents the structure name from becoming a valid <A REL=DEFINITION HREF="26_glo_t.htm#type_specifier"><I>type specifier</I></A> recognizable by <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A>. <P>
For example: <P>
<PRE>
(defstruct (quux (:type list) :named) x y)
</PRE>
</TT> <P>
should make a constructor that builds a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> exactly like the one that <A REL=DEFINITION HREF="f_list_.htm#list"><B>list</B></A> produces, with <TT>quux</TT> as its <A REL=DEFINITION HREF="26_glo_c.htm#car"><I>car</I></A>. <P>
If this type is defined: <P>
<PRE>
(deftype quux () '(satisfies quux-p))
</PRE>
</TT> then this form <P>
<PRE>
(typep (make-quux) 'quux)
</PRE>
</TT> should return precisely what this one does <P>
<PRE>
(typep (list 'quux nil nil) 'quux)
</PRE>
</TT> <P>
If <TT>:type</TT> is not supplied, the structure is represented as an <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A> of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="t_stu_ob.htm#structure-object"><B>structure-object</B></A>. <P>
<A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> without a <TT>:type</TT> option defines a <A REL=DEFINITION HREF="26_glo_c.htm#class"><I>class</I></A> with the structure name as its name. The <A REL=DEFINITION HREF="26_glo_m.htm#metaclass"><I>metaclass</I></A> of structure <A REL=DEFINITION HREF="26_glo_i.htm#instance"><I>instances</I></A> is <A REL=DEFINITION HREF="t_stu_cl.htm#structure-class"><B>structure-class</B></A>. <P>
<P></DL><P>
The consequences of redefining a <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> structure are undefined. <P>
In the case where no <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> options have been supplied, the following functions are automatically defined to operate on instances of the new structure: <P>
<P><DL><DT><B>Predicate</B> <P><DD>
A predicate with the name <TT></TT><I>structure-name</I><TT>-p</TT> is defined to test membership in the structure type. The predicate <TT>(</TT><I>structure-name</I><TT>-p </TT><I>object</I><TT>)</TT> is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A> if an <I>object</I> is of this <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A>; otherwise it is <A REL=DEFINITION HREF="26_glo_f.htm#false"><I>false</I></A>. <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A> can also be used with the name of the new <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> to test whether an <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A> belongs to the <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A>. Such a function call has the form <TT>(typep </TT><I>object</I><TT> '</TT><I>structure-name</I><TT>)</TT>. <P>
<DT><B>Component reader functions</B> <P><DD>
<A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>Reader</I></A> functions are defined to <A REL=DEFINITION HREF="26_glo_r.htm#read"><I>read</I></A> the components of the structure. For each slot name, there is a corresponding <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function with the name <TT></TT><I>structure-name</I><TT>-</TT><I>slot-name</I><TT></TT>. This function <A REL=DEFINITION HREF="26_glo_r.htm#read"><I>reads</I></A> the contents of that slot. Each <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> function takes one argument, which is an instance of the structure type. <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A> can be used with any of these <A REL=DEFINITION HREF="26_glo_r.htm#reader"><I>reader</I></A> functions to alter the slot contents. <P>
<DT><B>Constructor function</B> <P><DD>
A constructor function with the name <TT>make-</TT><I>structure-name</I><TT></TT> is defined. This function creates and returns new instances of the structure type. <P>
<DT><B>Copier function</B> <P><DD>
A copier function with the name <TT>copy-</TT><I>structure-name</I><TT></TT> is defined. The copier function takes an object of the structure type and creates a new object of the same type that is a copy of the first. The copier function creates a new structure with the same component entries as the original. Corresponding components of the two structure instances are <A REL=DEFINITION HREF="f_eql.htm#eql"><B>eql</B></A>. <P></DL><P>
If a <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> appears as a <A REL=DEFINITION HREF="26_glo_t.htm#top_level_form"><I>top level form</I></A>, the <A REL=DEFINITION HREF="26_glo_c.htm#compiler"><I>compiler</I></A> must make the <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> name recognized as a valid <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> name in subsequent declarations (as for <A REL=DEFINITION HREF="m_deftp.htm#deftype"><B>deftype</B></A>) and make the structure slot readers known to <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A>. In addition, the <A REL=DEFINITION HREF="26_glo_c.htm#compiler"><I>compiler</I></A> must save enough information about the <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> so that further <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> definitions can use <TT>:include</TT> in a subsequent <A REL=DEFINITION HREF="m_deftp.htm#deftype"><B>deftype</B></A> in the same <A REL=DEFINITION HREF="26_glo_f.htm#file"><I>file</I></A> to refer to the <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> name. The functions which <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> generates are not defined in the compile time environment, although the <A REL=DEFINITION HREF="26_glo_c.htm#compiler"><I>compiler</I></A> may save enough information about the functions to code subsequent calls inline. The <TT>#S</TT> <A REL=DEFINITION HREF="26_glo_r.htm#reader_macro"><I>reader macro</I></A> might or might not recognize the newly defined <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> name at compile time. <P>
<P><B>Examples:</B><P>
An example of a structure definition follows: <P>
<PRE>
(defstruct ship
x-position
y-position
x-velocity
y-velocity
mass)
</PRE>
</TT> This declares that every <TT>ship</TT> is an <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A> with five named components. The evaluation of this form does the following: <P>
<P><OL><LI> It defines <TT>ship-x-position</TT> to be a function of one argument, a ship, that returns the <TT>x-position</TT> of the ship; <TT>ship-y-position</TT> and the other components are given similar function definitions. These functions are called the <A REL=DEFINITION HREF="26_glo_a.htm#access"><I>access</I></A> functions, as they are used to <A REL=DEFINITION HREF="26_glo_a.htm#access"><I>access</I></A> elements of the structure. <P>
<LI> <TT>ship</TT> becomes the name of a <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> of which instances of ships are elements. <TT>ship</TT> becomes acceptable to <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A>, for example; <TT>(typep x 'ship)</TT> is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A> if <TT>x</TT> is a ship and false if <TT>x</TT> is any <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A> other than a ship. <P>
<LI> A function named <TT>ship-p</TT> of one argument is defined; it is a predicate that is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A> if its argument is a ship and is <A REL=DEFINITION HREF="26_glo_f.htm#false"><I>false</I></A> otherwise. <P>
<LI> A function called <TT>make-ship</TT> is defined that, when invoked, creates a data structure with five components, suitable for use with the <A REL=DEFINITION HREF="26_glo_a.htm#access"><I>access</I></A> functions. Thus executing <P>
<PRE>
(setq ship2 (make-ship))
</PRE>
</TT> sets <TT>ship2</TT> to a newly created <TT>ship</TT> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A>. One can supply the initial values of any desired component in the call to <TT>make-ship</TT> by using keyword arguments in this way: <P>
<PRE>
(setq ship2 (make-ship :mass *default-ship-mass*
:x-position 0
:y-position 0))
</PRE>
</TT> This constructs a new ship and initializes three of its components. This function is called the ``constructor function'' because it constructs a new structure. <P>
<LI> A function called <TT>copy-ship</TT> of one argument is defined that, when given a <TT>ship</TT> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A>, creates a new <TT>ship</TT> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A> that is a copy of the given one. This function is called the ``copier function.'' <P></OL><P>
<A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A> can be used to alter the components of a <TT>ship</TT>: <P>
<PRE>
(setf (ship-x-position ship2) 100)
</PRE>
</TT> This alters the <TT>x-position</TT> of <TT>ship2</TT> to be <TT>100</TT>. This works because <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> behaves as if it generates an appropriate <A REL=DEFINITION HREF="m_defset.htm#defsetf"><B>defsetf</B></A> for each <A REL=DEFINITION HREF="26_glo_a.htm#access"><I>access</I></A> function. <P>
<PRE>
;;;
;;; Example 1
;;; define town structure type
;;; area, watertowers, firetrucks, population, elevation are its components
;;;
(defstruct town
area
watertowers
(firetrucks 1 :type fixnum) ;an initialized slot
population
(elevation 5128 :read-only t)) ;a slot that can't be changed
=&gt; TOWN
;create a town instance
(setq town1 (make-town :area 0 :watertowers 0)) =&gt; #S(TOWN...)
;town's predicate recognizes the new instance
(town-p town1) =&gt; <A REL=DEFINITION HREF="26_glo_t.htm#true">true</A>
;new town's area is as specified by make-town
(town-area town1) =&gt; 0
;new town's elevation has initial value
(town-elevation town1) =&gt; 5128
;setf recognizes reader function
(setf (town-population town1) 99) =&gt; 99
(town-population town1) =&gt; 99
;copier function makes a copy of town1
(setq town2 (copy-town town1)) =&gt; #S(TOWN...)
(= (town-population town1) (town-population town2)) =&gt; <A REL=DEFINITION HREF="26_glo_t.htm#true">true</A>
;since elevation is a read-only slot, its value can be set only
;when the structure is created
(setq town3 (make-town :area 0 :watertowers 3 :elevation 1200))
=&gt; #S(TOWN...)
;;;
;;; Example 2
;;; define clown structure type
;;; this structure uses a nonstandard prefix
;;;
(defstruct (clown (:conc-name bozo-))
(nose-color 'red)
frizzy-hair-p polkadots) =&gt; CLOWN
(setq funny-clown (make-clown)) =&gt; #S(CLOWN)
;use non-default reader name
(bozo-nose-color funny-clown) =&gt; RED
(defstruct (klown (:constructor make-up-klown) ;similar def using other
(:copier clone-klown) ;customizing keywords
(:predicate is-a-bozo-p))
nose-color frizzy-hair-p polkadots) =&gt; klown
;custom constructor now exists
(fboundp 'make-up-klown) =&gt; <A REL=DEFINITION HREF="26_glo_t.htm#true">true</A>
;;;
;;; Example 3
;;; define a vehicle structure type
;;; then define a truck structure type that includes
;;; the vehicle structure
;;;
(defstruct vehicle name year (diesel t :read-only t)) =&gt; VEHICLE
(defstruct (truck (:include vehicle (year 79)))
load-limit
(axles 6)) =&gt; TRUCK
(setq x (make-truck :name 'mac :diesel t :load-limit 17))
=&gt; #S(TRUCK...)
;vehicle readers work on trucks
(vehicle-name x)
=&gt; MAC
;default taken from :include clause
(vehicle-year x)
=&gt; 79
(defstruct (pickup (:include truck)) ;pickup type includes truck
camper long-bed four-wheel-drive) =&gt; PICKUP
(setq x (make-pickup :name 'king :long-bed t)) =&gt; #S(PICKUP...)
;:include default inherited
(pickup-year x) =&gt; 79
;;;
;;; Example 4
;;; use of BOA constructors
;;;
(defstruct (dfs-boa ;BOA constructors
(:constructor make-dfs-boa (a b c))
(:constructor create-dfs-boa
(a &amp;optional b (c 'cc) &amp;rest d &amp;aux e (f 'ff))))
a b c d e f) =&gt; DFS-BOA
;a, b, and c set by position, and the rest are uninitialized
(setq x (make-dfs-boa 1 2 3)) =&gt; #(DFS-BOA...)
(dfs-boa-a x) =&gt; 1
;a and b set, c and f defaulted
(setq x (create-dfs-boa 1 2)) =&gt; #(DFS-BOA...)
(dfs-boa-b x) =&gt; 2
(eq (dfs-boa-c x) 'cc) =&gt; <A REL=DEFINITION HREF="26_glo_t.htm#true">true</A>
;a, b, and c set, and the rest are collected into d
(setq x (create-dfs-boa 1 2 3 4 5 6)) =&gt; #(DFS-BOA...)
(dfs-boa-d x) =&gt; (4 5 6)
</PRE>
</TT> <P>
<P><B>Affected By:</B> None.
<P>
<P><B>Exceptional Situations:</B><P>
<P>
If any two slot names (whether present directly or inherited by the <TT>:include</TT> option) are the <A REL=DEFINITION HREF="26_glo_s.htm#same"><I>same</I></A> under <A REL=DEFINITION HREF="f_stgeq_.htm#stringEQ"><B>string=</B></A>, <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> should signal an error of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="e_progra.htm#program-error"><B>program-error</B></A>. <P>
The consequences are undefined if the <I>included-structure-name</I> does not name a <A REL=DEFINITION HREF="26_glo_s.htm#structure"><I>structure</I></A> <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A>. <P>
<P><B>See Also:</B><P>
<P>
<A REL=DEFINITION HREF="f_docume.htm#documentation"><B>documentation</B></A>, <A REL=DEFINITION HREF="f_pr_obj.htm#print-object"><B>print-object</B></A>, <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A>, <A REL=DEFINITION HREF="f_subtpp.htm#subtypep"><B>subtypep</B></A>, <A REL=DEFINITION HREF="f_tp_of.htm#type-of"><B>type-of</B></A>, <A REL=DEFINITION HREF="f_typep.htm#typep"><B>typep</B></A>, <A REL=CHILD HREF="03_b.htm">Section 3.2 (Compilation)</A> <P>
<P><B>Notes:</B><P>
<P>
The <I>printer-name</I> should observe the values of such printer-control variables as <A REL=DEFINITION HREF="v_pr_esc.htm#STprint-escapeST"><B>*print-escape*</B></A>. <P>
The restriction against issuing a warning for type mismatches between a <I>slot-initform</I> and the corresponding slot's <TT>:type</TT> option is necessary because a <I>slot-initform</I> must be specified in order to specify slot options; in some cases, no suitable default may exist. <P>
The mechanism by which <A REL=DEFINITION HREF="#defstruct"><B>defstruct</B></A> arranges for slot accessors to be usable with <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A> is <A REL=DEFINITION HREF="26_glo_i.htm#implementation-dependent"><I>implementation-dependent</I></A>; for example, it may use <A REL=DEFINITION HREF="26_glo_s.htm#setf_function"><I>setf functions</I></A>, <A REL=DEFINITION HREF="26_glo_s.htm#setf_expander"><I>setf expanders</I></A>, or some other <A REL=DEFINITION HREF="26_glo_i.htm#implementation-dependent"><I>implementation-dependent</I></A> mechanism known to that <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementation</I></A>'s <A REL=DEFINITION HREF="26_glo_c.htm#code"><I>code</I></A> for <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A>. <P>
<P><HR>The following <A REL=META HREF="../Front/X3J13Iss.htm">X3J13 cleanup issues</A>, <I>not part of the specification</I>, apply to this section:<P><UL><LI> <A REL=CHILD HREF="../Issues/iss090.htm">DATA-TYPES-HIERARCHY-UNDERSPECIFIED</A><LI> <A REL=CHILD HREF="../Issues/iss119.htm">DEFSTRUCT-SLOTS-CONSTRAINTS-NAME:DUPLICATES-ERROR</A><LI> <A REL=CHILD HREF="../Issues/iss059.htm">COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY</A><LI> <A REL=CHILD HREF="../Issues/iss118.htm">DEFSTRUCT-REDEFINITION:ERROR</A><LI> <A REL=CHILD HREF="../Issues/iss275.htm">PRINT-CIRCLE-STRUCTURE:USER-FUNCTIONS-WORK</A><LI> <A REL=CHILD HREF="../Issues/iss117.htm">DEFSTRUCT-PRINT-FUNCTION-INHERITANCE:YES</A><LI> <A REL=CHILD HREF="../Issues/iss292.htm">REDUCE-ARGUMENT-EXTRACTION</A><LI> <A REL=CHILD HREF="../Issues/iss112.htm">DEFSTRUCT-COPIER-ARGUMENT-TYPE:RESTRICT</A><LI> <A REL=CHILD HREF="../Issues/iss113.htm">DEFSTRUCT-COPIER:ARGUMENT-TYPE</A><LI> <A REL=CHILD HREF="../Issues/iss110.htm">DEFSTRUCT-CONSTRUCTOR-OPTIONS:EXPLICIT</A><LI> <A REL=CHILD HREF="../Issues/iss305.htm">SETF-FUNCTIONS-AGAIN:MINIMAL-CHANGES</A><LI> <A REL=CHILD HREF="../Issues/iss120.htm">DEFSTRUCT-SLOTS-CONSTRAINTS-NUMBER</A><LI> <A REL=CHILD HREF="../Issues/iss111.htm">DEFSTRUCT-CONSTRUCTOR-SLOT-VARIABLES:NOT-BOUND</A><LI> <A REL=CHILD HREF="../Issues/iss355.htm">UNINITIALIZED-ELEMENTS:CONSEQUENCES-UNDEFINED</A><LI> <A REL=CHILD HREF="../Issues/iss114.htm">DEFSTRUCT-DEFAULT-VALUE-EVALUATION:IFF-NEEDED</A><LI> <A REL=CHILD HREF="../Issues/iss135.htm">DOCUMENTATION-FUNCTION-BUGS:FIX</A><LI> <A REL=CHILD HREF="../Issues/iss115.htm">DEFSTRUCT-INCLUDE-DEFTYPE:EXPLICITLY-UNDEFINED</A><LI> <A REL=CHILD HREF="../Issues/iss116.htm">DEFSTRUCT-PRINT-FUNCTION-AGAIN:X3J13-MAR-93</A><P></UL><HR>
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
</BODY>
</HTML>