User Tools

A PCRE internal error occured. This might be caused by a faulty plugin

====== Macro DEFINE-CONDITION ====== ====Syntax==== * **define-condition** //name (parent-type''*'') (slot-spec''*'') option''*''// → //name// <blockquote> //slot-spec// ::= //slot-name | (slot-name slot-option)// //slot-option// ::= <nowiki>[[</nowiki>{**'':reader''** //[[CL:Glossary:symbol]]//}''*'' | {**'':writer''** function-name}''*'' | {**'':accessor''** //[[CL:Glossary:symbol]]//}''*'' | {**'':allocation''** allocation-type} | {**'':initarg''** //[[CL:Glossary:symbol]]//}''*'' | {**'':initform''** //[[CL:Glossary:form]]//} | {**'':type''** //[[CL:Glossary:type specifier|type-specifier]]//} <nowiki>]]</nowiki> //option// ::= <nowiki>[[</nowiki>(**'':default-initargs''** ''.'' //initarg-list//) | (**'':documentation''** //[[CL:Glossary:string]]//) | (**'':report''** ''report-name'') <nowiki>]]</nowiki> //function-name// ::= {//[[CL:Glossary:symbol]]// | ([[CL:Macros:setf]] //[[CL:Glossary:symbol]])//}} //allocation-type// ::= {**'':instance''** | **'':class''**} //report-name// ::= {//[[CL:Glossary:string]]// | //[[CL:Glossary:symbol]]// | //[[CL:Glossary:lambda expression]]//} </blockquote> ====Arguments and Values==== * //name// - a //[[CL:Glossary:symbol]]//. * //parent-type// - a //[[CL:Glossary:symbol]]// naming a //[[CL:Glossary:condition]]// //[[CL:Glossary:type]]//. If no //parent-types// are supplied, the //parent-types// default to ''([[CL:Types:condition]])''. * //default-initargs// - a //[[CL:Glossary:list]]// of //[[CL:Glossary:keyword-value pair|keyword/value pairs]]//. * //slot-spec// -- the //[[CL:Glossary:name]]// of a //[[CL:Glossary:slot]]// or a //[[CL:Glossary:list]]// consisting of the //slot-name// followed by zero or more //slot-options//. * //slot-name// -- a slot name (a //[[CL:Glossary:symbol]]//), the //[[CL:Glossary:list]]// of a slot name, or the //[[CL:Glossary:list]]// of slot name/slot form pairs. * //option// -- Any of the following: * **'':reader''** - can be supplied more than once for a given //[[CL:Glossary:slot]]// and cannot be **[[CL:Constant Variables:nil]]**. * **'':writer''** - can be supplied more than once for a given //[[CL:Glossary:slot]]// and must name a //[[CL:Glossary:generic function]]//. * **'':accessor''** - can be supplied more than once for a given //[[CL:Glossary:slot]]// and cannot be **[[CL:Constant Variables:nil]]**. * **'':allocation''** - can be supplied once at most for a given //[[CL:Glossary:slot]]//. The default, if **'':allocation''** is not supplied, is **'':instance''**. * **'':initarg''** - can be supplied more than once for a given //[[CL:Glossary:slot]]//. * **'':initform''** - can be supplied once at most for a given //[[CL:Glossary:slot]]//. * **'':type''** - can be supplied once at most for a given //[[CL:Glossary:slot]]//. * **'':documentation''** - can be supplied once at most for a given //[[CL:Glossary:slot]]//. * **'':report''** - can be supplied once at most. ====Description==== **define-condition** defines a new condition type called //name//, which is a //[[CL:Glossary:subtype]]// of the //[[CL:Glossary:type]]// or //[[CL:Glossary:type|types]]// named by //parent-type//. Each //parent-type// argument specifies a direct //[[CL:Glossary:supertype]]// of the new //[[CL:Glossary:condition]]//. The new //[[CL:Glossary:condition]]// inherits //[[CL:Glossary:slot|slots]]// and //[[CL:Glossary:method|methods]]// from each of its direct //[[CL:Glossary:supertype|supertypes]]//, and so on. If a slot name/slot form pair is supplied, the slot form is a //[[CL:Glossary:form]]// that can be evaluated by **[[CL:Functions:make-condition]]** to produce a default value when an explicit value is not provided. If no slot form is supplied, the contents of the //slot// is initialized in an //[[CL:Glossary:implementation-dependent]]// way. If the //[[CL:Glossary:type]]// being defined and some other //[[CL:Glossary:type]]// from which it inherits have a slot by the same name, only one slot is allocated in the //[[CL:Glossary:condition]]//, but the supplied slot form overrides any slot form that might otherwise have been inherited from a //parent-type//. If no slot form is supplied, the inherited slot form (if any) is still visible. Accessors are created according to the same rules as used by **[[CL:Macros:defclass]]**. A description of //slot-options// follows: ===:reader=== The **'':reader''** slot option specifies that an //[[CL:Glossary:unqualified method]]// is to be defined on the //[[CL:Glossary:generic function]]// named by the argument to **'':reader''** to read the value of the given //[[CL:Glossary:slot]]//. ===:initform=== The **'':initform''** slot option is used to provide a default initial value form to be used in the initialization of the //[[CL:Glossary:slot]]//. This //[[CL:Glossary:form]]// is evaluated every time it is used to initialize the //[[CL:Glossary:slot]]//. The //[[CL:Glossary:lexical environment]]// in which this //[[CL:Glossary:form]]// is evaluated is the lexical //[[CL:Glossary:environment]]// in which the **define-condition** form was evaluated. Note that the //[[CL:Glossary:lexical environment]]// refers both to variables and to //[[CL:Glossary:functions]]//. For //[[CL:Glossary:local slot|local slots]]//, the //[[CL:Glossary:dynamic environment]]// is the dynamic //[[CL:Glossary:environment]]// in which **[[CL:Functions:make-condition]]** was called; for //[[CL:Glossary:shared slot|shared slots]]//, the //[[CL:Glossary:dynamic environment]]// is the //[[CL:Glossary:dynamic environment]]// in which the **define-condition** form was evaluated. No implementation is permitted to extend the syntax of **define-condition** to allow ''(//slot-name// //form//)'' as an abbreviation for ''(//slot-name// :initform //form//)''. ===:initarg=== The **'':initarg''** slot option declares an initialization argument named by its //[[CL:Glossary:symbol]]// argument and specifies that this initialization argument initializes the given //[[CL:Glossary:slot]]//. If the initialization argument has a value in the call to **[[CL:Functions:initialize-instance]]**, the value is stored into the given //[[CL:Glossary:slot]]//, and the slot's **'':initform''** slot option, if any, is not evaluated. If none of the initialization arguments specified for a given //[[CL:Glossary:slot]]// has a value, the //[[CL:Glossary:slot]]// is initialized according to the **'':initform''** slot option, if specified. ===:type=== The **'':type''** slot option specifies that the contents of the //[[CL:Glossary:slot]]// is always of the specified //[[CL:Glossary:type]]//. It effectively declares the result type of the reader generic function when applied to an //[[CL:Glossary:object]]// of this //[[CL:Glossary:condition]]// type. The consequences of attempting to store in a //[[CL:Glossary:slot]]// a value that does not satisfy the type of the //[[CL:Glossary:slot]]// is undefined. ===:default-initargs=== This option is treated the same as it would be **[[CL:Macros:defclass]]**. ===:documentation=== The **'':documentation''** slot option provides a //[[CL:Glossary:documentation string]]// for the //[[CL:Glossary:slot]]//. ===:report=== //[[CL:Glossary:condition|Condition]]// reporting is mediated through the **[[CL:Functions:print-object]]** method for the //[[CL:Glossary:condition]]// type in question, with **[[CL:Variables:star-print-escape-star|*print-escape*]]** always being **[[CL:Constant Variables:nil]]**. Specifying ''(:report //report-name//)'' in the definition of a condition type ''C'' is equivalent to: <blockquote> ([[CL:Macros:defmethod]] [[CL:Functions:print-object]] ((x c) stream) (if [[CL:Variables:star-print-escape-star|*print-escape*]] (call-next-method) (//report-name// x stream))) </blockquote> If the value supplied by the argument to **'':report''** (//report-name//) is a //[[CL:Glossary:symbol]]// or a //[[CL:Glossary:lambda expression]]//, it must be acceptable to **[[CL:Special Operators:function]]**. ''(function //report-name//)'' is evaluated in the current //[[CL:Glossary:lexical environment]]//. It should return a //[[CL:Glossary:function]]// of two arguments, a //[[CL:Glossary:condition]]// and a //[[CL:Glossary:stream]]//, that prints on the //[[CL:Glossary:stream]]// a description of the //[[CL:Glossary:condition]]//. This //[[CL:Glossary:function]]// is called whenever the //[[CL:Glossary:condition]]// is printed while **[[CL:Variables:star-print-escape-star|*print-escape*]]** is **[[CL:Constant Variables:nil]]**. If //report-name// is a //[[CL:Glossary:string]]//, it is a shorthand for ''([[CL:Symbols:lambda]] (condition stream) ([[CL:Symbols:declare]] ([[CL:Declarations:ignore]] condition)) ([[CL:Functions:write-string]] //report-name// stream))''. This option is processed after the new //[[CL:Glossary:condition]]// type has been defined, so use of the //slot// accessors within the **'':report''** function is permitted. If this option is not supplied, information about how to report this type of //[[CL:Glossary:condition]]// is inherited from the //parent-type//. ---- The consequences are unspecifed if an attempt is made to //[[CL:Glossary:read]]// a //slot// that has not been explicitly initialized and that has not been given a default value. The consequences are unspecified if an attempt is made to assign the //slots// by using **[[CL:Macros:setf]]**. If a **define-condition** //[[CL:Glossary:form]]// appears as a //[[CL:Glossary:top level form]]//, the //[[CL:Glossary:compiler]]// must make //name// recognizable as a valid //[[CL:Glossary:type]]// name, and it must be possible to reference the //[[CL:Glossary:condition]]// //[[CL:Glossary:type]]// as the //parent-type// of another //[[CL:Glossary:condition]]// //[[CL:Glossary:type]]// in a subsequent **define-condition** //[[CL:Glossary:form]]// in the //[[CL:Glossary:file]]// being compiled. ====Examples==== The following form defines a condition of //[[CL:Glossary:type]]// ''peg/hole-mismatch'' which inherits from a condition type called ''blocks-world-error'': <blockquote> (define-condition peg/hole-mismatch (blocks-world-error) ((peg-shape :initarg :peg-shape :reader peg/hole-mismatch-peg-shape) (hole-shape :initarg :hole-shape :reader peg/hole-mismatch-hole-shape)) (:report ([[CL:Symbols:lambda]] (condition stream) ([[CL:Functions:format]] stream "A ~A peg cannot go in a ~A hole." (peg/hole-mismatch-peg-shape condition) (peg/hole-mismatch-hole-shape condition))))) <r>PEG/HOLE-MISMATCH</r> </blockquote> The new type has slots ''peg-shape'' and ''hole-shape'', so **[[CL:Functions:make-condition]]** accepts '':peg-shape'' and '':hole-shape'' keywords. The //[[CL:Glossary:reader|readers]]// ''peg/hole-mismatch-peg-shape'' and ''peg/hole-mismatch-hole-shape'' apply to objects of this type, as illustrated in the **'':report''** information. The following form defines a //[[CL:Glossary:condition]]// //[[CL:Glossary:type]]// named ''machine-error'' which inherits from **[[CL:Types:error]]**: <blockquote> (define-condition machine-error (error) ((machine-name :initarg :machine-name :reader machine-error-machine-name)) (:report ([[CL:Symbols:lambda]] (condition stream) ([[CL::Functions:format]] stream "There is a problem with ~A." (machine-error-machine-name condition))))) <r>MACHINE-ERROR</r> </blockquote> Building on this definition, a new error condition can be defined which is a subtype of ''machine-error'' for use when machines are not available: <blockquote> (define-condition machine-not-available-error (machine-error) () (:report ([[CL:Symbols:lambda]] (condition stream) ([[CL::Functions:format]] stream "The machine ~A is not available." (machine-error-machine-name condition))))) <r>MACHINE-NOT-AVAILABLE-ERROR</r> </blockquote> This defines a still more specific condition, built upon ''machine-not-available-error'', which provides a slot initialization form for ''machine-name'' but which does not provide any new slots or report information. It just gives the ''machine-name'' slot a default initialization: <blockquote> (define-condition my-favorite-machine-not-available-error (machine-not-available-error) ((machine-name :initform "mc.lcs.mit.edu"))) <r>my-favorite-machine-not-available-error</r> </blockquote> Note that since no **'':report''** clause was given, the information inherited from ''machine-not-available-error'' is used to report this type of condition. <blockquote> (define-condition ate-too-much (error) ((person :initarg :person :reader ate-too-much-person) (weight :initarg :weight :reader ate-too-much-weight) (kind-of-food :initarg :kind-of-food :reader :ate-too-much-kind-of-food))) <r>ATE-TOO-MUCH</r> (define-condition ate-too-much-ice-cream (ate-too-much) ((kind-of-food :initform 'ice-cream) (flavor :initarg :flavor :reader ate-too-much-ice-cream-flavor :initform 'vanilla)) (:report ([[CL:Symbols:lambda]] (condition stream) ([[CL::Functions:format]] stream "~A ate too much ~A ice-cream" (ate-too-much-person condition) (ate-too-much-ice-cream-flavor condition))))) <r>ate-too-much-ice-cream</r> ([[CL:Functions:make-condition]] 'ate-too-much-ice-cream :person 'fred :weight 300 :flavor 'chocolate) <r>#<ATE-TOO-MUCH-ICE-CREAM 32236101> </r> (format t "~A" *) <o>FRED ate too much CHOCOLATE ice-cream</o> <r>[[CL:Constant Variables:nil|NIL]]</r> </blockquote> ====Affected By==== None. ====Exceptional Situations==== None. ====See Also==== **[[CL:Functions:make-condition|Function MAKE-CONDITION]]**, **[[CL:Macros:defclass|Macro DEFCLASS]]**, {\secref\ConditionSystemConcepts} ====Notes==== None. \issue{COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY} \issue{DEFINE-CONDITION-SYNTAX:INCOMPATIBLY-MORE-LIKE-DEFCLASS+EMPHASIZE-READ-ONLY} \issue{CLOS-CONDITIONS:INTEGRATE} \issue{CLOS-CONDITIONS:INTEGRATE} \issue{CLOS-CONDITIONS:INTEGRATE}