;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: Introduction to Structure Macros =Text: 3INTRODUCTION TO STRUCTURE MACROS* 2defstruct* provides a facility in Lisp for creating and using aggregate datatypes with named elements. These are like structures in PL/I, or records in Pascal. In the last two chapters we saw how to use macros to extend the control structures of Lisp; here we see how they can be used to extend Lisp's data structures as well. To explain the basic idea, assume you were writing a Lisp program that dealt with space ships. In your program, you want to represent a space ship by a Lisp object of some kind. The interesting things about a space ship, as far as your program is concerned, are its position (1x* and 1y*), velocity (1x* and 1y*), and mass. How do you represent a space ship? Well, the representation could be a list of the x-position, 1y* position, and so on. Equally well it could be an array of five elements, the zeroth being the 1x* position, the first being the 1y* position, and so on. The problem with both of these representations is that the ``elements'' (such as 1x* position) occupy places in the object which are quite arbitrary, and hard to remember (Hmm, was the mass the third or the fourth element of the array?). This would make programs harder to write and read. It would not be obvious when reading a program that an expression such as 2(cadddr ship1)* or 2(aref ship2 3)* means ``the 1y* component of the ship's velocity'', and it would be very easy to write 2caddr* in place of 2cadddr*. What we would like to see are names, easy to remember and to understand. If the symbol 2foo* were bound to a representation of a space ship, then 3(ship-x-position foo)* could return its 1x* position, and 3(ship-y-position foo)* its 1y* position, and so forth. The 2defstruct* facility does just this. 2defstruct* itself is a macro which defines a structure. For the space ship example above, we might define the structure by saying: 3(defstruct (ship)* 3 "Represents a space ship."* 3 ship-x-position* 3 ship-y-position* 3 ship-x-velocity* 3 ship-y-velocity* 3 ship-mass)* This says that every 2ship* is an object with five named components. (This is a very simple case of 2defstruct*; we will see the general form later.) The evaluation of this form does several things. First, it defines 2ship-x-position* to be a function which, given a ship, returns the 1x* component of its position. This is called an 1accessor function*, because it 1accesses* a component of a structure. 2defstruct* defines the other four accessor functions analogously. 2defstruct* also defines 2make-ship* to be a macro or function (you can specify which one) that can create a 2ship* object. So 2(setq s (make-ship))* makes a new ship, and sets 2s* to it. This is called the 1constructor*, because it constructs a new structure. We also want to be able to change the contents of a structure. To do this, we use the 2setf* macro (see 4(EVAL-2)setf*), as follows (for example): 3(setf (ship-x-position s) 100)* Here 2s* is bound to a ship, and after the evaluation of the 2setf* form, the 2ship-x-position* of that ship is 100. Another way to change the contents of a structure is to use the alterant macro, which is described later, in 4(DEFSTRUCT-2)Alterant Macros*. How does all this map into the familiar primitives of Lisp? In this simple example, we left the choice of implementation technique up to 2defstruct*; by default, it chooses to represent a ship as an array. The array has five elements, which are the five components of the ship. The accessor functions are defined thus: 3(defun ship-x-position (ship)* 3 (aref ship 0))* The constructor form 2(make-ship)* performs 2(make-array 5)*, which makes an array of the appropriate size to be a ship. Note that a program which uses ships need not contain any explicit knowledge that ships are represented as five-element arrays; this is kept hidden by 2defstruct*. The accessor functions are not actually ordinary functions; instead they are substs (see 4(FUNCTIONS-1)Interpreted Functions*). This difference has two implications: it allows 2setf* to understand the accessor functions, and it allows the compiler to substitute the body of an accessor function directly into any function that uses it, making compiled programs that use 2defstruct* exactly equal in efficiency to programs that ``do it by hand''. Thus writing 2(ship-mass s)* is exactly equivalent to writing 2(aref s 4)*, and writing 2(setf (ship-mass s) m)* is exactly equivalent to writing 2(setf (aref s 4) m)*, when the program is compiled. It is also possible to tell 2defstruct* to implement the accessor functions as macros; this is not normally done in Zetalisp, however. We can now use the 2describe-defstruct* function to look at the 2ship* object, and see what its contents are: 3(describe-defstruct x 'ship) =>* 3# is a ship* 3 ship-x-position: 100* 3 ship-y-position: nil* 3 ship-x-velocity: nil* 3 ship-y-velocity: nil* 3 ship-mass: nil* 3#* (The 2describe-defstruct* function is explained more fully on 4(DEFSTRUCT-1)How to Use Defstruct*.) By itself, this simple example provides a powerful structure definition tool. But, in fact, 2defstruct* has many other features. First of all, we might want to specify what kind of Lisp object to use for the ``implementation'' of the structure. The example above implemented a ship as an array, but 2defstruct* can also implement structures as array-leaders, lists, and other things. (For array-leaders, the accessor functions call 2array-leader*, for lists, 2nth*, and so on.) Most structures are implemented as arrays. Lists take slightly less storage, but elements near the end of a long list are slower to access. Array leaders allow you to have a homogeneous aggregate (the array) and a heterogeneous aggregate with named elements (the leader) tied together into one object. Packages are this sort of an object, and so are the strings which Zmacs uses for storing lines of text. The constructor function or macro allows you to specify values for slots in the new structure. 2defstruct* allows you to specify default initial values for slots; whenever a structure is constructed and no value is specified for a slot, the slot's default initial value is stored in it. The 2defstruct* in Zetalisp also works in various dialects of Maclisp, and so it has some features that are not useful in Zetalisp. When possible, the Maclisp-specific features attempt to do something reasonable or harmless in Zetalisp, to make it easier to write code that will run equally well in Zetalisp and Maclisp. (Note that this 2defstruct* is not necessarily the one installed in Maclisp!) Note that there is another version of 2defstruct* used in Common Lisp programs, which is slightly incompatible. See 4(DEFSTRUCT-2)Common Lisp Defstruct*. =Node: How to Use Defstruct =Text: 3HOW TO USE DEFSTRUCT defstruct* 1Macro* A call to 2defstruct* looks like: 3(defstruct (1name* 1options2...**)* 3 [1doc-string*]* 3 1slot-description-1** 3 1slot-description-2** 3 2...*)* 1name* must be a symbol; it is the name of the structure. It is given a 2si:defstruct-description* property that describes the attributes and elements of the structure; this is intended to be used by programs that examine Lisp programs and that want to display the contents of structures in a helpful way. 1name* is used for other things, described below. Each 1option* may be either a symbol, which should be one of the recognized option names listed in the next section, or a list, whose car should be one of the option names and the rest of which should be arguments to the option. Some options have arguments that default; others require that arguments be given explicitly. 1doc-string* is a string which is recorded as the documentation of 1name* as a structure. It can be accessed via 2(documentation '1name* 'structure)*. It is not required. Each 1slot-description* may be in any of three forms: 2(1)3 1slot-name*** 2(2)3 (1slot-name* [1default-init* 1slot-options**...3])** 2(3)3 ((1slot-name-1* 1byte-spec-1* [1default-init-1* 1slot-options**...3])** 3 (1slot-name-2* 1byte-spec-2* [1default-init-2* 1slot-options2...**])* 3 2...*)* Each 1slot-description* allocates one element of the physical structure, even though in form (3) several slots are defined. Each 1slot-name* must always be a symbol; an accessor function is defined for each slot. In form (1), 1slot-name* simply defines a slot with the given name. An accessor function is defined with the name 1slot-name* (but see the 2:conc-name* option, 4(DEFSTRUCT-1)Options to Defstruct*). Form (2) is similar, but allows a default initialization for the slot. Initialization is explained further on 4(DEFSTRUCT-2)Constructors*. Form (3) lets you pack several slots into a single element of the physical underlying structure, using the byte field feature of 2defstruct*, which is explained on 4(DEFSTRUCT-2)Byte Fields*. Forms (2) and (3) allow 1slot-options* which are alternating keywords and values (unevaluated). These slot option keywords are defined: 2:read-only 1flag** If 1flag* is non-2nil*, this specifies that this slot should not be changed in an existing structure. 2setf* will not be allowed on the slot's accessor. 2:type 1type-spec** Declares that the contents of this slot must be of type 1type-spec*. The Lisp machine compiler does not use this information, but sometimes it enables 2defstruct* to deduce that it can pack the structure into less space by using a specialized array type. 2:documentation 1documentation-string** Makes 1documentation-string* the documentation for the slot's accessor function. It also goes in the 2si:defstruct-slot-description-documentation* for this slot in the 2defstruct-description* structure. Here is an eggsample of using slot options: 3(defstruct (eggsample :named :conc-name) * 3 (yolk 'a* 3 :documentation "First thing you need in an eggsample.") * 3 (grade 3) * 3 (albumen nil :read-only t)) * 3(documentation 'eggsample-yolk 'function)* 3=> "First thing you need in an eggsample." * 3(setf (eggsample-albumen (make-eggsample)) 'eggsistential)* 3>>ERROR: SETF is forbidden on EGGSAMPLE-ALBUMEN.* 3While in the function ...* Because evaluation of a 2defstruct* form causes many functions and macros to be defined, you must take care not to define the same name with two different 2defstruct* forms. A name can only have one function definition at a time; if it is redefined, the latest definition is the one that takes effect, and the earlier definition is clobbered. (This is no different from the requirement that each 2defun* which is intended to define a distinct function must have a distinct name.) To systematize this necessary carefulness, as well as for clarity in the code, it is conventional to prefix the names of all of the accessor functions with some text unique to the structure. In the example above, all the names started with 2ship-*. The 2:conc-name* option can be used to provide such prefixes automatically (see 4(DEFSTRUCT-1)Options to Defstruct*). Similarly, the conventional name for the constructor in the example above was 2make-ship*, and the conventional name for the alterant macro (see 4(DEFSTRUCT-2)Alterant Macros*) was 2alter-ship*. The 2describe-defstruct* function lets you examine an instance of a structure. 3describe-defstruct* 1instance* &optional 1name* 2describe-defstruct* takes an 1instance* of a structure, and prints out a description of the instance, including the contents of each of its slots. 1name* should be the name of the structure; you must provide the name of the structure so that 2describe-defstruct* can know what structure 1instance* is an instance of, and therefore figure out what the names of the slots of 1instance* are. If 1instance* is a named structure, you don't have to provide 1name*, since it is just the named structure symbol of 1instance*. Normally the 2describe* function (see 4(MISCELL-1)Poking Around in the Lisp World*) calls 2describe-defstruct* if it is asked to describe a named structure; however some named structures have their own idea of how to describe themselves. See 4(DEFSTRUCT-2)Named Structures* for more information about named structures. =Node: Options to Defstruct =Text: 3OPTIONS TO DEFSTRUCT* This section explains each of the options that can be given to 2defstruct*. Here is an example that shows the typical syntax of a call to 2defstruct* that gives several options. 3(defstruct (foo (:type (:array (mod 256)))* 3 (:make-array (:leader-length 3))* 3 :conc-name* 3 (:size-macro foo))* 3 a b) 2:type** The 2:type* option specifies what kind of Lisp object to use to implement the structure. It must be given one argument, which must be one of the symbols enumerated below, or a user-defined type. If the option itself is not provided, the type defaults to 2:array* in traditional programs, or 2:vector* in Common Lisp programs. You can define your own types; this is explained in 4(DEFSTRUCT-3)Extensions to Defstruct*. 2:list* Uses a list. 2:named-list* Like 2:list*, but the first element of the list holds the symbol that is the name of the structure and so is not used as a component. 2:array* 2:typed-array* 2:vector*These are all synonymous. They use an array, storing components in the body of the array. 2:named-array* Like 2:array*, but makes the array a named structure (see 4(DEFSTRUCT-2)Named Structures*) using the name of the structure as the named structure symbol. Element 0 of the array holds the named structure symbol and so is not used to hold a component of the structure. 2:named-typed-array* 2:named-vector*These two synonyms are like 2:named-array* but the array always has a leader and the named structure symbol is stored there. As a result, it is possible to use the 2:subtype* option to specify a restricted array type, such as 2art-8b*. 2:phony-named-vector* This is what you get in Common Lisp if you say 2(:type :vector)* and 2:named*. 2:array-leader* Use an array, storing components in the leader of the array. (See the 2:make-array* option, described below.) 2:named-array-leader* Like 2:array-leader*, but makes the array a named structure (see 4(DEFSTRUCT-2)Named Structures*) using the name of the structure as the named structure symbol. Element 1 of the leader holds the named structure symbol and so is not used to hold a component of the structure. 2:fixnum-array* Like 2:array*, but the type of the array is 2art-32b*. 2:flonum-array* Like 2:array*, but the type of the array is 2art-float*. 2:named-fixnum-array* 2:named-flonum-array*Like 2:fixnum-array* or 2:flonum-array* but also a named structure, with a leader to hold the named structure symbol. 2:tree* The structure is implemented out of a binary tree of conses, with the leaves serving as the slots. 2:fixnum* This unusual type implements the structure as a single fixnum. The structure may only have one slot. This is only useful with the byte field feature (see 4(DEFSTRUCT-2)Byte Fields*); it lets you store a bunch of small numbers within fields of a fixnum, giving the fields names. 2:grouped-array* This is described in 4(DEFSTRUCT-2)Grouped Arrays*. The argument of 2:type* may also have the form 2(1type* 1subtype*)*. This is equivalent to specifying 1type* for the 2:type* option and 1subtype* for the 2:subtype* option. For example, 2(:type (:array (mod 16.)))* specifies an array of four-bit bytes. 2:subtype* For structures which are arrays, 2:subtype* permits the array type to be specified. It requires an argument, which must be either an array type name such as 2art-4b* or a type specifier restricting the elements of the array. In other words, it should be a suitable value for either the 1type* or the 1element-type* argument to 2make-array*. If no 2:subtype* option is specified but a 2:type* slot option is given for every slot, 2defstruct* may deduce a subtype automatically to make the structure more compact. See 4(PRIMOBJTYPE-0)Primitive Object Types* for more information on type specifiers. 2:constructor* Specifies how to make a constructor for the structure. In the simplest use, there is one argument, which specifies the name to give to the standard keyword-argument constructor. If the argument is not provided or if the option itself is not provided, the name of the constructor is made by concatenating the string 2"make-"* to the name of the structure. If the argument is provided and is 2nil*, no constructor is defined. More complicated usage is explained in 4(DEFSTRUCT-2)Constructors*. 2:alterant* Takes one argument, which specifies the name of the alterant macro. If the argument is not provided, the name of the alterant is made by concatenating the string 2"alter-"* to the name of the structure. If the argument is provided and is 2nil*, no alterant is defined. Use of the alterant macro is explained in 4(DEFSTRUCT-2)Alterant Macros*. In Common Lisp programs, the default for 2:alterant* is 2nil*; no alterant is defined. In traditional programs, the default is 2alter-1name**. 2:predicate* Causes 2defstruct* to generate a predicate to recognize instances of the structure. Naturally it only works for ``named'' types. The argument to the 2:predicate* option is the name of the predicate. If the option is present without an argument, then the name is formed by concatenating `2-p*' to the end of the name symbol of the structure. If the option is not present, then no predicate is generated. Example: 3(defstruct (foo :named :predicate)* 3 a* 3 b)* defines a single argument function, 2foo-p*, that is true only of instances of this structure. The defaulting of the 2:predicate* option is different (and complicated) in Common Lisp programs. See 4(DEFSTRUCT-2)Common Lisp Defstruct*. 2:copier* Causes 2defstruct* to generate a single argument function that can copy instances of this structure. Its argument is the name of the copying function. If the option is present without an argument, then the name is formed by concatenating `2copy-*' with the name of the structure. Example: 3(defstruct (foo (:type :list) :copier)* 3 foo-a* 3 foo-b)* Generates a function approximately like: 3(defun copy-foo (x)* 3 (list (car x) (cadr x))) 2:default-pointer** Normally, the accessors defined by 2defstruct* expect to be given exactly one argument. However, if the 2:default-pointer* argument is used, the argument to each accessor is optional. If the accessor is used with no argument, it evaluates the default-pointer form to find a structure and accesses the appropriate component of that structure. Here is an example: 3(defstruct (room * 3 (:default-pointer *default-room*))* 3 room-name* 3 room-contents)* 3(room-name x) ==> (aref x 0)* 3(room-name) ==> (aref *default-room* 0)* If the argument to the 2:default-pointer* argument is not given, it defaults to the name of the structure. 2:conc-name* It is conventional to begin the names of all the accessor functions of a structure with a specific prefix, usually the name of the structure followed by a hyphen. The 2:conc-name* option allows you to specify this prefix and have it concatenated onto the front of all the slot names to make the names of the accessor functions. The argument should be a string to be used as the prefix, or a symbol whose pname is to be used. If 2:conc-name* is specified without an argument, the prefix is the name of the structure followed by a hyphen. If the argument is 2nil* or 2""*, the names of the accessors are the same as the slot names, and it is up to you to name the slots according to some suitable convention. In Common Lisp programs, the default for 2:conc-name*, when this option is not specified, is the structure name followed by a hyphen. For traditional programs, the default is 2nil*. The keywords recognized by the constructor and alterant are the slot names, not the accessor names, transfered into the keyword package. It is important to keep this in mind when using 2:conc-name*, since it causes the slot and accessor names to be different. Here is an example: 3(defstruct (door :conc-name)* 3 knob-color* 3 width)* 3(setq d (make-door :knob-color 'red :width 5.0))* 3(door-knob-color d) ==> red 2:include** Builds a new structure definition as an extension of an old structure definition. Suppose you have a structure called 2person* that looks like this: 3(defstruct (person :named :conc-name)* 3 name* 3 age* 3 sex)* Now suppose you want to make a new structure to represent an astronaut. Since astronauts are people too, you would like them to also have the attributes of name, age, and sex, and you would like Lisp functions that operate on 2person* structures to operate just as well on 2astronaut* structures. You can do this by defining 2astronaut* with the 2:include* option, as follows: 3(defstruct (astronaut :named (:include person) * 3 :conc-name)* 3 helmet-size* 3 (favorite-beverage 'tang))* The argument to the 2:include* option is required, and must be the name of some previously defined structure of the same type as this structure. 2:include* does not work with structures of type 2:tree* or of type 2:grouped-array*. The 2:include* option inserts the slots of the included structure at the front of the list of slots for this structure. That is, an 2astronaut* has five slots; first the three defined in 2person*, and then after those the two defined in 2astronaut* itself. The accessor functions defined by the 2person* structure, such as 2person-name*, can be used also on 2astronaut*'s. New accessor functions are generated for these slots in the 2astronaut* structure as if they were defined afresh; their names start with 2astronaut-* instead of 2person-*. In fact, the functions 2person-age* and 2astronaut-age* receive identical definitions. Since the structures are named structures, recognizable by 2typep*, 2subtypep* considers 2astronaut* a subtype of 2person*, and 2typep* considers any 2astronaut* to be of type 2person*. The following examples illustrate how you can construct and use 2astronaut* structures: 3(setq x (make-astronaut :name 'buzz* 3 :age 45.* 3 :sex t* 3 :helmet-size 17.5))* 3(person-name x) => buzz* 3(astronaut-name x) => buzz* 3(astronaut-favorite-beverage x) => tang* 3(typep x 'astronaut) => t* 3(typep x 'person) => t* Note that the 2:conc-name* option was 1not* inherited from the included structure; it is present for 2:astronaut* only because it was specified explicitly in the definition. Similarly, the 2:default-pointer* and 2:but-first* options are not inherited from the 2:include*'d structure. The following is an advanced feature. Sometimes, when one structure includes another, the default values or slot options for the slots that came from the included structure are not what you want. The new structure can specify new default values or slot options for the included slots by giving the 2:include* option as: 3(:include 1name new-descriptor-1 2...* new-descriptor-n*)* Each 1new-slot-descriptor* is just like the slot descriptors used for defining new slots, except that byte fields are not allowed. The default initialization specified in 1new-slot-descriptor*, or the absence of one, overrides what was specified in the included structure type (2person*). Any slot option values specified in 1new-slot-descriptor* also override the values given in the included structure's definition. Any inherited slots for which no 1new-slot-descriptor* is given, and any slot options not explicitly overridden, are inherited. For example, if we had wanted to define 2astronaut* so that the default age for an astronaut is 245.*, and provide documentation for its accessor, then we could have said: 3(defstruct (astronaut :conc-name* 3 (:include person * 3 (age 45. :documentation* 3 "The ASTRONAUT's age in years.")))* 3 helmet-size* 3 (favorite-beverage 'tang))* If the 2:read-only* option is specified as 2nil* when 2t* would have been inherited, an error is signaled. 2:named* This means that you want to use one of the ``named'' types. If you specify a type of 2:array*, 2:array-leader*, or 2:list*, and give the 2:named* option, then the 2:named-array*, 2:named-array-leader*, or 2:named-list* type is used instead. Asking for type 2:array* and giving the 2:named* option as well is the same as asking for the type 2:named-array*; the only difference is stylistic. The 2:named* option works quite differently in Common Lisp programs; see 4(DEFSTRUCT-2)Common Lisp Defstruct*. 2:make-array* If the structure being defined is implemented as an array, this option may be used to control those aspects of the array that are not otherwise constrained by 2defstruct*. For example, you might want to control the area in which the array is allocated. Also, if you are creating a structure of type 2:array-leader*, you almost certainly want to specify the dimensions of the array to be created, and you may want to specify the type of the array. The argument to the 2:make-array* option should be a list of alternating keyword symbols for the 2make-array* function (see 4(ARRAYS-1)Constructing Arrays*), and forms whose values are the arguments to those keywords. For example, 2(:make-array (:area* 2'permanent-storage-area))* would request that the array be allocated in a particular area. Note that the keyword symbol is 1not* evaluated. 2defstruct* overrides any of the 2:make-array* options that it needs to. For example, if your structure is of type 2:array*, then 2defstruct* supplies the size of that array regardless of what you say in the 2:make-array* option. If you use the 2:initial-element* 2make-array* option, it initializes all the slots, but 2defstruct*'s own initializations are done afterward. If a subtype has been specified to or deduced by 2defstruct*, it overrides any 2:type* keyword in the 2:make-array* argument. Constructors for structures implemented as arrays recognize the keyword argument 2:make-array*. Attributes supplied therein overide any 2:make-array* option attributes supplied in the original 2defstruct* form. If some attribute appears in neither the invocation of the constructor nor in the 2:make-array* option to 2defstruct*, then the constructor chooses appropriate defaults. The 2:make-array* option may only be used with the default style of constructor that takes keyword arguments. If a structure is of type 2:array-leader*, you probably want to specify the dimensions of the array. The dimensions of an array are given to 2:make-array* as a position argument rather than a keyword argument, so there is no way to specify them in the above syntax. To solve this problem, you can use the keyword 2:dimensions* or the keyword 2:length* (they mean the same thing), with a value that is anything acceptable as 2make-array*'s first argument. 2:times* Used for structures of type 2:grouped-array* to control the number of repetitions of the structure to be allocated by the constructor. (See 4(DEFSTRUCT-2)Grouped Arrays*.) The constructor also accepts a keyword argument 2:times* to override the value given in the 2defstruct*. If 2:times* appears in neither the invocation of the constructor nor as a 2defstruct* option, the constructor allocates only one instance of the structure. 2:size-macro* Defines a special macro to expand into the size of this structure. The exact meaning of the size varies, but in general this number is the one you would need to know if you were going to allocate one of these structures yourself (for example, the length of the array or list). The argument of the 2:size-macro* option is the name to be used for the macro. If this option is present without an argument, then the name of the structure is concatenated with `2-size*' to produce the macro name. Example: 3(defstruct (foo :conc-name :size-macro)* 3 a b)* 3(macroexpand '(foo-size)) => 2 2:size-symbol** Like 2:size-macro* but defines a global variable rather than a macro. The size of the structure is the variable's value. Use of 2:size-macro* is considered cleaner. 2:initial-offset* This allows you to tell 2defstruct* to skip over a certain number of slots before it starts allocating the slots described in the body. This option requires an argument (which must be a fixnum), which is the number of slots you want 2defstruct* to skip. To make use of this option requires that you have some familiarity with how 2defstruct* is implementing your structure; otherwise, you will be unable to make use of the slots that 2defstruct* has left unused. 2:but-first* This option is best explained by example: 3(defstruct (head (:type :list)* 3 (:default-pointer person)* 3 (:but-first person-head))* 3 nose* 3 mouth* 3 eyes)* The accessors expand like this: 3(nose x) ==> (car (person-head x))* 3(nose) ==> (car (person-head person))* The idea is that 2:but-first*'s argument is an accessor from some other structure, and it is never expected that this structure will be found outside of that slot of that other structure. Actually, you can use any one-argument function, or a macro that acts like a one-argument function. It is an error for the 2:but-first* option to be used without an argument. 2:callable-accessors* Controls whether accessors are really functions, and therefore ``callable'', or whether they are really macros. With an argument of 2t*, or with no argument, or if the option is not provided, then the accessors are really functions. Specifically, they are substs, so that they have all the efficiency of macros in compiled programs, while still being function objects that can be manipulated (passed to 2mapcar*, etc.). If the argument is 2nil* then the accessors are really macros. 2:callable-constructors* Controls whether constructors are really functions, and therefore ``callable'', or macros. An argument of 2t* makes them functions; 2nil* makes them macros. The default is 2t* in Common Lisp programs, 2nil* in traditional programs. See 4(DEFSTRUCT-2)Constructors* for more information. 2:property* For each structure defined by defstruct, a property list is maintained for the recording of arbitrary properties about that structure. (That is, there is one property list per structure definition, not one for each instantiation of the structure.) The 2:property* option can be used to give a 2defstruct* an arbitrary property. 2(:property* 1property-name value2)** gives the 2defstruct* a 1property-name* property of 1value*. Neither argument is evaluated. To access the property list, the user must look inside the 2defstruct-description* structure himself (see 4(DEFSTRUCT-3)The si:defstruct-description Structure*). 2:print* Controls the printed representation of his structure in a way independent of the Lisp dialect in use. Here is an example: 3(defstruct (foo :named* 3 (:print "#"* 3 (foo-a foo) (foo-b foo)))* 3 foo-a* 3 foo-b)* Of course, this only works if you use some named type, so that the system can recognize examples of this structure automatically. The arguments to the 2:print* option are arguments to the 2format* function (except for the stream of course!). They are evaluated in an environment where the name symbol of the structure (2foo* in this case) is bound to the instance of the structure to be printed. This works by generating a 2defselect* that creates a named structure handler. Do not use the 2:print* option if you define a named structure handler yourself, as they will conflict. 2:print-function* is the Common Lisp version of the 2:print* option. Its argument is a function to print a structure of this type, and it is called with three arguments: the structure to be printed, the stream to print it on, and the current printing depth (which should be compared with 2*print-level** to decide when to cut off recursion and print `2#*'). The function is expected to observe the values of the various printer-control variables such as 2*print-escape** (see 4(READPRINT-1)Options that Control Printing*). Example: 3(defstruct (bar :named :conc-name* 3 (:print-function* 3 (lambda (struct stream depth)* 3 depth ;2 unused** 3 (sys:printing-random-object* 3 (struct stream :type)* 3 (format stream "with zap ~S"* 3 (bar-zap struct))))))* 3 "The famous BAR structure."* 3 (zap 'yow)* 3 random-slot)* 3(make-bar) => # 1type** In addition to the options listed above, any currently defined type (any legal argument to the 2:type* option) can be used as an option. This is mostly for compatibility with the old version of 2defstruct*. It allows you to say just 1type* instead of 2(:type 1type*)*. It is an error to give an argument to one of these options. 1other* Finally, if an option isn't found among those listed above, it should be a valid defstruct-keyword for the type of structure being defined, and the option should be of the form 2(1option-name value*)*. If so, the option is treated just like 2(:property* 1option-name value2)**. That is, the 2defstruct* is given an 1option-name* property of 1value*. This provides a primitive way for you to define your own options to 2defstruct*, particularly in connection with user-defined types (see 4(DEFSTRUCT-3)Extensions to Defstruct*). Several of the options listed above are actually implemented using this mechanism. They include 2:times*, 2:subtype* and 2:make-array*. The valid defstruct-keywords of a type are in a list in the 2defstruct-keywords* slot of the 2defstruct-type-description* structure for 1type*.