;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: Using the Constructor and Alterant =Text: 3USING THE CONSTRUCTOR AND ALTERANT* After you have defined a new structure with 2defstruct*, you can create instances of this structure using the constructor, and you can alter the values of its slots using the alterant macro. By default, traditional 2defstruct* defines both the constructor and the alterant, forming their names by concatenating `2make-*' and `2alter-*', respectively, onto the name of the structure. The 2defstruct* for Common Lisp programs defines no alterant by default. You can specify the names yourself by passing the name you want to use as the argument to the 2:constructor* or 2:alterant* options, or specify that you don't want the macro created at all by passing 2nil* as the argument. =Node: Constructors =Text: 3CONSTRUCTORS* A call to a constructor, in general, has the form 3(1name-of-constructor* 1keyword-1* 1value-1* 1keyword-2* 1value-2* 2...*)* Each 1keyword* is a keyword (a symbol in the 2keyword* package) whose name matches one of the slots of the structure, or one of a few specially recognized keywords. The name of the constructor is specified by the 2:constructor* option, which can also specify a documentation string for it: 3(:constructor 1name-of-constructor* [1doc-string*])* If a 1keyword* matches the name of a slot (1not* the name of an accessor), then the corresponding 1value* is used to initialize that slot of the new structure. Any slots whose values are not specified in this way are initialized to the values of the default initial value forms specified in the 2defstruct*. If no default initial value was specified either for a slot, that slot's initial value is undefined. You should always specify the initialization, either in the 2defstruct* or in the constructor invocation, if you care about the initial value of the slot. Constructors may be macros or functions. They are functions if the 2:callable-constructors* option to 2defstruct* is non-2nil*. By default, they are functions in Common Lisp programs and macros in traditional programs. Constructor macros allow the slot name (in its own package) to be used instead of a keyword. Constructor functions do not, as they are ordinary functions defined using 2&key*. Old code using slot names not in the keyword package should be converted. The default initial value forms are evaluated (if needed) each time a structure is constructed, so that if 2(gensym)* is used as a default initial value form then a new symbol is generated for each structure. The order of evaluation of the default initial value forms is unpredictable. When the constructor is a macro, the order of evaluation of the keyword argument forms it is given is also unpredictable. The two special keyword arguments recognized by constructors are 2:make-array* and 2:times*. 2:make-array* should be used only for structures which are represented as arrays, and 2:times* only for 2:grouped-array* structures. If one of these arguments is given, then it overrides the 2:make-array* option or the 2:times* option (see 4(DEFSTRUCT-1)Options to Defstruct*) specified in the 2defstruct*. For example: For example, 3'c with a constructor macro* 3(make-ship :ship-x-position 10.0* 3 :ship-y-position 12.0* 3 :make-array '(:leader-length 5 :area disaster-area))* 3'c * or with a constructor function 3'c (make-ship :ship-x-position 10.0* 3'c :ship-y-position 12.0* 3'c :make-array '(:leader-length 5 :area disaster-area))* 'c Note that the argument of a special keyword is evaluated if the 'c constructor is a function, but not if it is a macro. This 'c incompatibility is unfortunately unavoidable. User-defined types of structures can define their own special constructor keywords. =Node: By-Position Constructors =Text: 3BY-POSITION CONSTRUCTORS* If the 2:constructor* option is given as 2(:constructor 1name* 1arglist* [1doc-string*])*, then instead of making a keyword driven constructor, 2defstruct* defines a positional constructor, taking arguments whose meaning is determined by the argument's position rather than by a keyword. The 1arglist* is used to describe what arguments the constructor should accept. In the simplest case something like 2(:constructor make-foo (a b c))* defines 2make-foo* to be a three-argument constructor macro whose arguments are used to initialize the slots named 2a*, 2b*, and 2c*. In addition, the keywords 2&optional*, 2&rest*, and 2&aux* are recognized in the argument list. They work in the way you might expect, but there are a few fine points worthy of explanation: 3(:constructor make-foo * 3 (a &optional b (c 'sea) &rest d &aux e (f 'eff))* 3 "Make a FOO, with positional arguments")* This defines 2make-foo* to be a constructor of one or more arguments. The first argument is used to initialize the 2a* slot. The second argument is used to initialize the 2b* slot. If there isn't any second argument, then the default value given in the body of the 2defstruct* (if given) is used instead. The third argument is used to initialize the 2c* slot. If there isn't any third argument, then the symbol 2sea* is used instead. Any arguments following the third argument are collected into a list and used to initialize the 2d* slot. If there are three or fewer arguments, then 2nil* is placed in the 2d* slot. The 2e* slot 1is not initialized*; its initial value is undefined, even if a default value was specified in its slot-description. Finally, the 2f* slot is initialized to contain the symbol 2eff*. The actions taken in the 2b* and 2e* cases were carefully chosen to allow the user to specify all possible behaviors. Note that the aux ``variables'' can be used to override completely the default initializations given in the body. Since there is so much freedom in defining constructors this way, it would be cruel to only allow the 2:constructor* option to be given once. So, by special dispensation, you are allowed to give the 2:constructor* option more than once, so that you can define several different constructors, each with a different syntax. These may include both keyword and positional constructors. If there are multiple keyword constructors, they all behave the same, differing only in the name. 2It is important to have a keyword constructor* because otherwise the 2#S* reader construct cannot work. Note that positional constructors may be macros or functions, just like keyword constructors, and based on the same criterion: they are functions if the 2:callable-constructors* option to 2defstruct* is non-2nil*. By default, they are functions in Common Lisp programs and macros in traditional programs. If the positional constructor is a macro, then the actual order of evaluation of its arguments is unpredictable. Also note that you cannot specify the 2:make-array* or 2:times* information in a positional constructor. =Node: Alterant Macros =Text: 3ALTERANT MACROS* A call to the alterant macro, in general, has the form 3(1name-of-alterant-macro* 1instance-form* * 3 1slot-name-1* 1form-1** 3 1slot-name-2* 1form-2** 3 1...*)* 1instance-form* is evaluated and should return an instance of the structure. Each 1form* is evaluated and the corresponding slot is changed to have the result as its new value. The slots are altered after all the 1forms* are evaluated, so you can exchange the values of two slots, as follows: 3(alter-ship enterprise* 3 :ship-x-position (ship-y-position enterprise)* 3 :ship-y-position (ship-x-position enterprise))* As with constructor macros, the order of evaluation of the 1forms* is undefined. Using the alterant macro can produce more efficient Lisp than using consecutive 2setf*s when you are altering two byte fields of the same object, or when you are using the 2:but-first* option. =Node: Byte Fields =Text: 3BYTE FIELDS* The byte field feature of 2defstruct* allows you to specify that several slots of your structure are bytes (see 4(NUMBERS-2)Byte Manipulation Functions*) in an integer stored in one element of the structure. For example, suppose we had the following structure: 3(defstruct (phone-book-entry (:type :list))* 3 name* 3 address* 3 (area-code 617.)* 3 exchange* 3 line-number)* This works correctly but it wastes space. Area codes and exchange numbers are always less than 1000, and so both can fit into 10 bit fields when expressed as binary numbers. Since Lisp Machine fixnums have (more than) 20 bits, both of these values can be packed into a single fixnum. To tell 2defstruct* to do so, you can change the structure definition to the following: 3(defstruct (phone-book-entry (:type :list))* 3 name* 3 address* 3 ((area-code (byte 10. 10.) 617.)* 3 (exchange (byte 10. 0)))* 3 line-number)* The expressions 2(byte ...)* calculate byte specifiers to be used with the functions 2ldb* and 2dpb*. The accessors, constructor, and alterant will now operate as follows: 3(area-code pbe) ==> (ldb (byte 10. 10.) (caddr pbe))* 3(exchange pbe) ==> (ldb (byte 10. 0) (caddr pbe))* 3(make-phone-book-entry* 3 :name "Fred Derf"* 3 :address "259 Octal St."* 3 :exchange ex* 3 :line-number 7788.)* 3==> (list "Fred Derf" "259 Octal St." * 3 (dpb ex (byte 10. 0) 631808.)* 3 7788.)* 3(alter-phone-book-entry pbe* 3 :area-code ac* 3 :exchange ex)* 3==> ((lambda (#:g0530)* 3 (setf (nth 2 #:g0530)* 3 (dpb ac (byte 10. 10.) * 3 (dpb ex (byte 10. 0) (nth 2 #:g0530)))))* 3 pbe)* (This is how the expression would print; this text would not read in properly because a new uninterned symbol would be created by each use of 3#:*.) Note that the alterant macro is optimized to only read and write the second element of the list once, even though you are altering two different byte fields within it. This is more efficient than using two 2setf*'s. Additional optimization by the alterant macro occurs if the byte specifiers in the 2defstruct* slot descriptions are constants. However, you don't need to worry about the details of how the alterant macro does its work. If the byte specifier is 2nil*, then the accessor is defined to be the usual kind that accesses the entire Lisp object, thus returning all the byte field components as a fixnum. These slots may have default initialization forms. The byte specifier need not be a constant; a variable or, indeed, any Lisp form, is legal as a byte specifier. It is evaluated each time the slot is accessed. Of course, unless you are doing something very strange you will not want the byte specifier to change between accesses. Constructors (both functions and macros) initialize words divided into byte fields as if they were deposited in in the following order: 1) Initializations for the entire word given in the defstruct form. 2) Initializations for the byte fields given in the defstruct form. 3) Initializations for the entire word given in the constructor invocation. 4) Initializations for the byte fields given in the constructor invocation. Alterant macros work similarly: the modification for the entire Lisp object is done first, followed by modifications to specific byte fields. If any byte fields being initialized or altered overlap each other, the action of the constructor and alterant is unpredictable. =Node: Grouped Arrays =Text: 3GROUPED ARRAYS* The grouped array feature allows you to store several instances of a structure side-by-side within an array. This feature is somewhat limited; it does not support the 2:include* and 2:named* options. The accessor functions are defined to take an extra argument, which should be an integer, and is the index into the array of where this instance of the structure starts. This index should normally be a multiple of the size of the structure, for things to make sense. Note that the index is the 1first* argument to the accessor function and the structure is the 1second* argument, the opposite of what you might expect. This is because the structure is 2&optional* if the 2:default-pointer* option is used. Note that the ``size'' of the structure (for purposes of the 2:size-symbol* and 2:size-macro* options) is the number of elements in 1one* instance of the structure; the actual length of the array is the product of the size of the structure and the number of instances. The number of instances to be created by the constructor is taken from the 2:times* keyword of the constructor or the argument to the 2:times* option to 2defstruct*. =Node: Named Structures =Text: 3NAMED STRUCTURES* The 1named structure* feature provides a very simple form of user-defined data type. (Flavors are another, more powerful, facility for defining data types, but they are more expensive in simple cases. See 4(FLAVOR-0)Objects, Message Passing, and Flavors*.) A named structure is actually an array, containing elements and optionally a leader. The difference between a named structure and an ordinary array is that the named structure also contains an explicit slot to hold its ostensible data type. This data type is a symbol, any symbol the programmer cares to use. In traditional programs, named structures are normally defined using 2defstruct* with the 2:named* option. In Common Lisp programs, 2defstruct* defines a named structure by default. Individual named structures are made with the constructors defined by 2defstruct*. The data type symbol of a named structure is also called the 1named structure symbol*. It is stored in array element 0 if the structure has no leader. If there is a leader, the type symbol is stored in array leader element 1 (recall that element 0 is reserved for the fill pointer). If a numeric-type array is to be a named structure, it must have a leader, since a symbol cannot be an element of a numeric array. Named structure are 1recognizable*; that is, if you define a named structure called 2foo*, you can always tell whether an object is a 2foo* structure. No array created in the normal fashion, no matter what components it has, will be mistaken for a genuine 2foo*. Named structures can recognized by 2typep*. Specify 2foo*, the named structure name, as the second argument, and the object to be tested as the first argument. 2type-of* of an ordinary array returns 2array*, but 2type-of* of a named structure returns the explicitly recorded data type symbol. 3(defstruct (foo :named) a b)* 3(type-of (make-foo)) => foo* 3(typep (make-foo) 'foo) => t* Named structures of other types which include 2foo* are also recognized as 2foo*'s by 2typep*. For example, using the previously-given definitions of 2person* and 2astronaut*, then 3(typep (make-astronaut) 'person) => t* because the type 2person* was explicitly included by the 2defstruct* for 2astronaut*. Indirect includes count also: 3(defstruct (mission-specialist :named* 3 (:include astronaut))* 3 2...*)* 3(typep (make-mission-specialist) 'person) => t* 3(subtypep 'person 'mission-specialist) => t* It should be emphasized that the named structure 1is* an array. All the usual array functions, such as 2aref* and 2array-dimension*, can be used on it. If it is one-dimensional (as is usually the case) then the named structure is a vector and the generic sequence functions can be used on it. 3(typep (make-astronaut) 'array) => t* 3(arrayp (make-astronaut)) => t* 3(array-rank (make-astronaut)) => 1* Because named structure data types are recognizable, they can define generic operations and say how to handle them. A few such operations are defined by the system and are invoked automatically from well-defined places. For example 2print* automatically invokes the 2:print-self* operation if you give it a named structure. Thus, each type of named structure can define how it should print. The standardly defined named structure operations are listed below. You can also define new named structure operations and invoke them by calling the named structure as a function just as you would invoke a flavor instance. Operations on a named structure are all handled by a single function, which is found as the 2named-structure-invoke* property of the structure type symbol. It is OK for a named structure type to have no handler function. Then invocation of any operation on the named structure returns 2nil*, and system routines such as 2print* take default actions. If a handler function exists, it is given these arguments: 1operation* The name of the operation being invoked; usually a keyword. 1structure* The named structure which is being operated on. 1additional-arguments...* Any other arguments which were passed when the operation was invoked. The handler function should have a rest parameter so it can accept any number of arguments. The handler function should return 2nil* if it does not recognize the 1operation*. These are the named structure operations used by the system at present: 2:which-operations* Should return a list of the names of the operations the function handles. Every handler function must handle this operation, and every opertation that the function handles should be included in this list. 2:print-self* Should output the printed representation of the named structure to a stream. The additional arguments are the stream to output to, the current depth in list-structure, and the current value of 2*print-escape**. If 2:print-self* is not in the value returned by 2:which-operations*, or if there is no handler function, 2print* uses 2#s* syntax. 2:describe* Is invoked by 2describe* and should output a description of the structure to 2*standard-output**. If there is no handler function or 2:describe* is not in its 2:which-operations* list, 2describe* prints the names and values of the structure's fields as defined in the 2defstruct*. 2:sxhash* Is invoked by 2sxhash* and should return a hash code to use as the value of 2sxhash* for this structure. It is often useful to call 2sxhash* on some (perhaps all) of the components of the structure and combine the results in some way. There is one additional argument to this operation: a flag saying whether it is permissible to use the structure's address in forming the hash code. For some kinds of structure, there may be no way to generate a good hash code except to use the address. If the flag is 2nil*, they must simply do the best they can, even if it means always returning zero. It is permissible to return 2nil* for 2:sxhash*. Then 2sxhash* produces a hash code in its default fashion. 2:fasd-fixup* Is invoked by 2fasload* on a named structure that has been created from data in a QFASL file. The purpose of the operation is to give the structure a chance to ``clean itself up'' if, in order to be valid, it needs to have contents that are not exactly identical to those that were dumped. For example, readtables push themselves onto the list 2si:*all-readtables** so that they can be found by name. For most kinds of structures it is acceptable not to define this operation at all (so that it returns 2nil*). Example handler function: 3(defun (:property person named-structure-invoke)* 3 (op self &rest args)* 3 (selectq op* 3 (:which-operations '(:print-self :describe))* 3 (:describe* 3 (format (car args)* 3 "This is a ~D-year-old person"* 3 (person-age self)))* 3 (:print-self* 3 (if *print-escape** 3 (si:printing-random-object (self (car args) :type)* 3 (princ (person-name self) (car args)))* 3 (princ (person-name self) (car args))))))* or 3(defselect ((:property person named-structure-handler)* 3 ignore)* 3 (:print-self (self stream ignore &optional ignore)* 3 (if *print-escape** 3 (si:printing-random-object (self stream :type)* 3 (princ (person-name self) stream))* 3 (princ (person-name self) stream)))* 3 (:describe (self)* 3 (format *standard-output** 3 "This is a ~D-year-old person"* 3 (person-age self))))* This handler causes a person structure to include its name in its printed representation; it also causes 2princ* of a person to print just the name, with no `2#<*' syntax. This simple example could have been done even more simply with the 2:print-function* option. It is often convenient to define a handler function with 2defselect*; but you must be careful. 2defselect* by default defines the function to signal an error if it is called with a first argument that is not recognized. A handler function should return 2nil* and get no error. To avoid the problem, specify 2ignore* as the default handler when you write the 2defselect*. See 4(FUNCTIONS-2)Function-Defining Special Forms*. Note that the handler function of a named structure type is 1not* inherited by other named structure types that include it. For example, the above definition of a handler for 2person* has no effect at all on the 2astronaut* structure. If you need such inheritance, you must use flavors rather than named structures (see 4(FLAVOR-0)Objects, Message Passing, and Flavors*). The following functions operate on named structures. 3named-structure-p* 1x* This semi-predicate returns 2nil* if 1x* is not a named structure; otherwise it returns 1x*'s named structure symbol. 3make-array-into-named-structure* 1array* Marks 1array* as a named structure and returns it. This is used by 2make-array* when creating named structures. You should not normally call it explicitly. 3named-structure-invoke* 1operation* 1structure* &rest 1args* Invokes a named structure operation on 1structure*. 1operation* should be a keyword symbol, and 1structure* should be a named structure. The handler function of the named structure symbol, found as the value of the 2named-structure-invoke* property of the symbol, is called with appropriate arguments. If the structure type has no 2named-structure-invoke* property, 2nil* is returned. By convention, 2nil* is also returned by the handler if it does not recognize 2operation*. 2(send 1structure* 1operation* 1args*...)* has the same effect, by calling 2named-structure-invoke*. See also the 2:named-structure-symbol* keyword to 2make-array*, 4(ARRAYS-1)Constructing Arrays*. =Node: Common Lisp Defstruct =Text: 3COMMON LISP DEFSTRUCT cli:defstruct* 1Macro* The version of 2defstruct* used in Common Lisp programs differs from the traditional 2defstruct* in the defaults for a few options and the meanings of a few of them. The 2:conc-name* option defaults to the structure type name followed by a hyphen in 2cli:defstruct*. In traditional 2defstruct* it defaults to 2nil*. The 2:callable-constructors* option defaults to 2t* in 2cli:defstruct*, so that the constructor is a function. Traditionally, it defaults to 2nil*. The 2:alterant* option defaults to 2nil* in 2cli:defstruct*, so that no alterant is defined. Traditionally, an alterant is defined by default with the name 2alter-1name**. The 2:type* option defaults to 2:named-vector* in 2cli:defstruct*. This makes a named structure, and you may specify how to print it. The 2:predicate* option defaults to 2t* in this case. If the 2:type* option is specified in 2cli:defstruct*, you never get a named structure. You get either a plain list or a plain vector. There is no type-testing predicate, and you may not request one. You may not say how to print the structure, either. If you specify the 2:named* option along with 2:type*, you still 1do not* get a named structure. You get a plain list or a plain vector in which the structure name happens to be stored. The type is either 2:named-list* or 2:phony-named-vector*. The 2:predicate* option defaults to 2nil*, but you may specify 2t* yourself. However, any randomly created list or vector with the structure name stored in the right place will satisfy the predicate thus defined. 2typep* cannot recognize these phony named structures, and you may not specify how to print them (they do not understand 2named-structure-invoke*.)