This section describes the options to
defflavor
. For information on the format of the options, see the special formdefflavor
.See the section "Inheritance of
defflavor
Options".:abstract-flavor
Declares that the flavor exists only to define a protocol; it is not intend-ed to be instantiatintend-ed by itself. Instead, it is intendintend-ed to have more spe-cialized flavors mixed in before being instantiated.
Trying to instantiate an abstract flavor signals an error.
:abstract-flavor
is an advanced feature that affects paging. It decreases paging and usage of virtual memory by allowing abstract flavors to have combined methods. Normally, only instantiated flavors get combined methods, which are small Lisp functions that are automatically built and compiled by the flavor system to call all of the methods that are being combined to make the effective method. Sometimes many different in-stantiated flavors use the same combination of methods. If this is the case, and the abstract flavor’s combined methods are the same ones thatare needed by the instantiated flavors, then all instantiated flavors can simply share the combined methods of the abstract flavor instead of hav-ing to each make their own. This sharhav-ing improves performance because it reduces the working set.
compile-flavor-methods
is permitted on an abstract flavor. It is useful for combined methods that most specializations of that flavor would be able to share.(
:area-keyword
symbol)Changes the
:area
keyword tomake-instance
of this flavor to the sup-plied argument. This is useful if the flavor is using the:area
keyword for some other purpose, such as an init keyword for an object’s geomet-ric or geographic area. This option is similar to the:conc-name
option.Whereas
:conc-name
enables you to supply a prefix for an automatically generated function, the:area-keyword
option todefflavor
enables you to rename the:area
keyword that is given tomake-instance
when making an instance of this flavor.In rare cases, you might want to use the keyword
:area
for other pur-poses. For example, a geometric program might have atriangle
flavor that has an instance variable namedarea
that is equal to one-half of the product of its width and height. It is then important to distinguish be-tween the instance variablearea
and the keyword that denotes in which area to create instances. You can rename that keyword for the affected flavor by providing the:area-keyword
keyword todefflavor
. For exam-ple:(defflavor triangle (area) ;instance var.
()
:initable-instance-variables (:area-keyword :cons-area))
Now, when you make an instance,
:area
refers to the instance variable, and:cons-area
indicates the area in which instances are to be created:(make-instance ’triangle :area 44.23
:cons-area GEOMETRY-AREA)
(
:component-order
args...)Enables you to state explicitly the ordering constraints for the flavor components whose order is important. You can use it to relax ordering constraints on component flavors for which order is not important. You can also use it to add ordering constraints on flavors that are not com-ponents; this means that if this flavor is later mixed with another flavor, the ordering of components takes into account the constraints given by this option.
If
:component-order
is given, the order of flavor components at the top of thedefflavor
form is no longer significant. The arguments to:component-order
are lists. The members of each list are constrained to appear in the order they appear in the list. Any component that does not appear in these lists has no ordering constraints placed on it.For example, the following form imposes many constraints on the order-ing of the seven flavor components:
(defflavor foo (var1 var2) (a b c d e f g))
However, your program might not depend on a specific ordering of com-ponents, because the components have no effect on each other. For ex-ample, your program might depend only these ordering constraints:
• Flavor
c
must preceded
.• Flavor
b
must precedeg
.• If flavor
x
is present (it could be a component of one of the compo-nents, or it could be mixed into flavorfoo
to create a new flavor), it must followb
and precedeg
.You can specify those restrictions by giving the following option to
defflavor
:(defflavor foo (var1 var2) (a b c d e f g)
(:component-order (c d) (b x g)))
Note that this does not constrain flavors
c
andd
to precede flavorsb
,x
, andg
. Also, it is not an error to specify an ordering constraint for a fla-vor that is not a component of this flafla-vor. For example, it is valid to constrain the order ofx
, althoughx
might not be a direct or indirect component of this flavor.For details on the way the flavor system determines the order of flavor components, see the section "Ordering Flavor Components".
(
:conc-name
symbol)Enables you to specify a prefix for the accessor functions created when the
:readable-instance-variables
,:writable-instance-variables
, or:locatable-instance-variables
options are supplied. Normally the accessor function to access the instance variable v of flavor f is named f-v, such as:ship-mass
You can specify a different prefix as follows:
(defflavor ship (captain mass) () (:conc-name get-)
:readable-instance-variables)
The accessor functions for
ship
are thus namedget-captain
andget-mass
.You can use
:conc-name
to specify no prefix as follows:(defflavor ship (captain mass) () (:conc-name nil)
:readable-instance-variables)
The accessor functions for
ship
are namedcaptain
andmass
.For information on an alternate syntax of
defflavor
which enables you to explicitly specify the names of accessor functions, see the section " Speci-fying Names for Functions that Access Instance Variables".(
:constructor
args...)Automatically generates a constructor function that enables you to create new instances of this flavor. The main advantage to constructor func-tions is that they are much faster than using
make-instance
. Whereasmake-instance
takes a flavor name argument and looks up information about the flavor, constructor functions have this information compiled in-to Lisp code. Construcin-tor functions run anymake-instance
methods that are defined for this flavor.The constructor function can take positional arguments instead of key-word arguments, or a mix of positional and keykey-word arguments. You can give the
:constructor
option more than once within a singledefflavor
to define several different constructors, each with its own arguments.It is necessary to do a
compile-flavor-methods
to ensure that the con-structor function is defined. The concon-structor function is defined as part of the macro-expansion ofcompile-flavor-methods
, not part of the macro-expansion ofdefflavor
. This makes it possible to define a flavor before all component flavors are defined. If you are incrementally devel-oping code, you can put acompile-flavor-methods
form into an editor buffer and use c-sh-C before running code that calls the constructor function.The
:constructor
option takes two arguments. The first argument speci-fies the name of the constructor function. The second argument is op-tional; it is used to describe the argument list of the constructor. If no second argument is given, the constructor function uses the same&key
arglist thatmake-instance
would accept after the flavor name, including keywords for: each initable instance variable, each init-keyword, and:area
.For example, a simple case like
(:constructor make-foo (a b c))
definesmake-foo
to be a three-argument constructor function whose arguments are used to initialize the instance variables nameda
,b
, andc
.In addition, you can use the keywords
&optional
,&rest
,&key
,&allow-other-keys
, and&aux
in the argument list. They work as you might ex-pect, but note the following:(defflavor foo (a b c d e f g h i) () (:constructor make-foo
(a &optional b (c ’sea)
&rest d
&key i
&aux e (f ’eff))))
(compile-flavor-methods foo)
This defines
make-foo
to be a constructor that accepts one or more ar-guments. The first argument is used to initialize thea
instance variable.The second argument is used to initialize the
b
instance variable. If there is no second argument, then the default value given in the body of thedefflavor
(if given) is used instead. The third argument is used to initialize thec
instance variable. If there is no third argument, then the symbolsea
is used instead. Any arguments following the third argument are collected into a list and used to initialize thed
instance variable. If the keyword:i
is supplied with a value, that value is used to initialize thei
instance variable. If there are three or fewer arguments, thennil
is placed in thed
instance variable; the initial value ofe
is undefined;and the
f
instance variable is initialized to contain the symboleff
.The actions taken in the
b
ande
cases were carefully chosen to allow you to specify all possible behaviors. Note that the&aux
"variables" can be used to completely override the default initializations given in thedefflavor
form.In summary, each parameter of a constructor can be:
• The name of an instance variable. In this case, the argument is stored into the instance variable.
• Something that matches the area keyword; by default this is
:area
, but the:area-keyword
option can be used to specify a different area keyword. In this case, the argument is the area in which the instance is created.• Something that matches an init keyword declared by the
:init-keyword
option. In this case, the argument is passed to themake-instance
and/or:init
methods as the appropriate keyword argument.Above, "something that matches" means the following: For
&key
param-eters, something matches if it iseq
to the keyword. Note the(&key ((:key
var)))
syntax can be used to specify a keyword that is different from the variable name. For non-&key
parameters, something matches if it iseq
to a symbol with the same name as the parameter variable, but in the keyword package.Defaulting occurs as follows: If no default is specified in the constructor argument list, then the default is not
nil
(unlike the behavior of anor-mal argument list). Instead, for
&aux
parameters the default is to leave the instance variable unbound or not pass the init keyword to themake-instance
and/or:init
methods. For non-&aux
parameters, if no default is specified then default is whatever default thatmake-instance
would use.The area defaults the same regardless of whether it is
&aux
or not, since it is impossible not to have an area for making an instance.(
:default-handler
function-name)The argument is the name of a function that is to be called when a generic function is called for which there is no method. The function is called with the arguments the instance was called with, including the message name; the values it returns are returned. If this option is not specified on any component flavor, it defaults to a function that signals an error.
The function specified with the
:default-handler
option todefflavor
re-ceives two additional arguments. The first argument isself
and the sec-ond is alwaysnil
.The following example shows the use of
:default-handler
.(defflavor lisp-stream (forward) () (:default-handler lisp-stream-forward))
(defun lisp-stream-forward (self ignore message &rest arguments) (lexpr-funcall (send self :forward) message arguments))
This is equivalent to defining a method for the
:unclaimed-message
message. See the message:unclaimed-message
.(
:default-init-plist
plist)Provides a list of alternating keywords and default value forms for key-word arguments that are allowed for
make-instance
of this flavor. The keywords can be: initable instance variables, init keywords, required init keywords,:allow-other-keys
, or:area
. If you do not specify one or more of these keywords as arguments tomake-instance
, they are set to the default in:default-init-plist
. For the meaning of the:allow-other-keys
and:area
keywords, see the functionmake-instance
.This option allows one component flavor to default an option to another component flavor. The value forms are evaluated only when and if they are used. For example, the following would provide a default "frob array"
for any instance for which the user did not provide one explicitly as an argument to
make-instance
:(:default-init-plist :frob-array (make-array 100))
Elements in the
:default-init-plist
that are init keywords are supplied to any methods defined formake-instance
of this flavor. However,:default-init-plist
elements that initialize instance variables are not supplied tomake-instance
methods.(
:documentation
string)The list of arguments to this option is remembered on the flavor’s prop-erty list as the
:documentation
property. The convention for this list is as follows: A string describes what the flavor is for; this could consist of a brief overview in the first line followed by several paragraphs of de-tailed documentation. A symbol is one of the following keywords::mixin
A flavor that you might want to mix with others to provide a useful feature.:essential-mixin
A flavor that must be mixed in to all flavors of its class, or inappropriate behavior follows.:lowlevel-mixin
A mixin used only to build other mixins.:combination
A combination of flavors for a specific purpose.:special-purpose
A flavor used for some internal purpose by a particu-lar program, which is not intended for general use.
(
:functions
internal-function-names)Declares the names of
defun-in-flavor
functions internal to the flavor.The arguments are names of internal functions.
defun-in-flavor
functions are lexically scoped. They must either be de-fined before their callers, or declared by using the:functions
option fordefflavor
. Otherwise the caller would not be compiled or evaluated in the proper lexical environment, and would not know that the name of the internal function refers to adefun-in-flavor
function rather than to an ordinary function in the global environment. see the section "Defining Functions Internal to Flavors".The
:functions
option is not appropriate for internal functions defined bydefsubst-in-flavor
ordefmacro-in-flavor
.(
:gettable-instance-variables
vars...)This option is available for compatibility with the old message-passing flavor system. When writing new code, it is good practice to use the
:readable-instance-variables
option instead.Enables automatic generation of methods for getting the values of in-stance variables. The message name is the name of the variable, in the keyword package (that is, put a colon in front of it.)
To use the automatically-generated method, use the old
send
syntax. For example:(send my-ship :mass)
You can give this option with arguments, to specify the instance vari-ables to which it applies. If no arguments are provided, this option ap-plies to all instance variables listed at the top of the
defflavor
form.(
:init-keywords
symbols...)Declares its arguments as keywords that should be accepted by
make-instance
of this flavor. Init keywords are:• Keyword arguments to be processed by methods defined for
make-instance
for this flavorWhen you write a method for
make-instance
that accepts keyword ar-guments, you should include those keywords as init keywords. For re-lated information, see the section "Writing Methods formake-instance
".• Keywords defined by the
:mixture
option todefflavor
When you define a family of flavors, you should include any
:mixture
keywords as init keywords.
:init-keywords
is used for error-checking when you create an instance.All keywords given to
make-instance
are either initable instance vari-ables or init keywords, or keywords accepted bymake-instance
, like:area
. If the caller misspells a keyword or otherwise uses a keyword that no component flavor handles,make-instance
signals an error.Note that whenever you have a
:required-init-keywords
clause contain-ing keywords that are to be used bymake-instance
methods, it is neces-sary to include those keywords in the:init-keywords
clause as well.It is allowed but pointless to include keywords that initialize instance variables as init keywords.
(
:initable-instance-variables
vars...)Enables you to initialize the specified instance variables when making an instance of this flavor. The instance variables are sometimes called initable. In the
make-instance
form, you initialize values by including the keyword (name of the instance variable) followed by its value, as fol-lows:(make-instance flavor-name :variable-name value)
For example, when making an instance of the
ship
flavor, we can initial-ize themass
instance variable (assuming it is initable), as follows:(make-instance ’ship :mass 105)
You can give this option with arguments, to specify the instance vari-ables to which it applies. If no arguments are provided, this option ap-plies to all instance variables listed at the top of the
defflavor
form.If you want to specify that an instance variable inherited from another component flavor should be initable, you can include the name of that in-stance variable explicitly in the top of the
defflavor
form. This option checks for spelling errors, so any instance variables that are declaredinitable must appear at the top of the
defflavor
form, or be in the list of:required-instance-variables
.defflavor
offers an alternate syntax enabling you to explicitly specify the keyword to be used to initialize an instance variable. For information on it, see the section "Specifying Names for Functions that Access Instance Variables".(
:locatable-instance-variables
vars...)Enables you to use
locf
to get a locative pointer to the cell inside an in-stance that contains the value of an inin-stance variable as follows:(locf (accessor object))
If the accessor function is
ship-mass
, and the object ismy-ship
, you can get a locative pointer to the cell insidemy-ship
containing the value of themass
instance variable as follows:(locf (ship-mass my-ship))
You can give this option with arguments, to specify the instance vari-ables to which it applies. If no arguments are provided, this option ap-plies to all instance variables listed at the top of the
defflavor
form.Any instance variables specified by
:locatable-instance-variables
are au-tomatically made readable as well; that is, an accessor function is auto-matically defined.defflavor
offers an alternate syntax enabling you to explicitly specify the names of accessor functions. For information on it, see the section " Spec-ifying Names for Functions that Access Instance Variables".(
:method-combination
symbol)Declares the way that methods from different flavors are to be combined.
The syntax is:
(:method-combination generic-function name
generic-function (name args...)
...)
If the
:method-combination
option is also supplied todefgeneric
, that option must agree with the:method-combination
option given todefflavor
.For further details on usage and an example, see the section "Using the
:method-combination
Option".(
:method-order
generic-function-names)The arguments are names of generic functions that are frequently used or for which speed is important. Their handlers are inserted into the handler hash table first, so that they are found by the first hash probe.
(
:mixture
specs...)Defines a family of related flavors. The organization of this family
usual-ly consists of one basic flavor and several mixin flavors. The flavors in the family are automatically constructed by mixing various mixins with the basic flavor. When
make-instance
is called, it uses its keyword argu-ments (or defaults to values in the:default-init-plist
of thedefflavor
form) to choose which flavor of the family to instantiate.The basic flavor is the one that includes the
:mixture
option in itsThe basic flavor is the one that includes the