![[LISPWORKS]](../Graphics/LWSmall.gif)
![[Common Lisp HyperSpec (TM)]](../Graphics/CLHS_Sm.gif) 
 ![[Previous]](../Graphics/Prev.gif)
![[Up]](../Graphics/Up.gif)
![[Next]](../Graphics/Next.gif)
Syntax:
define-condition name (parent-type*) ({slot-spec}*) option*
=> name
slot-spec::= slot-name | (slot-name slot-option)
slot-option::= [[{:reader symbol}* |  
               {:writer function-name}* |  
               {:accessor symbol}* |  
               {:allocation allocation-type} |  
               {:initarg symbol}* |  
               {:initform form} |  
               {:type type-specifier} ]] 
 
option::= [[(:default-initargs . initarg-list) |  
          (:documentation string) |  
          (:report report-name) ]] 
 
function-name::= {symbol | (setf symbol)} 
 allocation-type::= :instance | :class
report-name::= string | symbol | lambda expression
Arguments and Values:
name---a symbol.
parent-type---a symbol naming a condition type. If no parent-types are supplied, the parent-types default to (condition).
default-initargs---a list of keyword/value pairs.
Slot-spec -- the name of a slot or a list consisting of the slot-name followed by zero or more slot-options.
Slot-name -- a slot name (a symbol), the list of a slot name, or the list of slot name/slot form pairs.
Option -- Any of the following:
Description:
define-condition defines a new condition type called name, which is a subtype of the type or types named by parent-type. Each parent-type argument specifies a direct supertype of the new condition. The new condition inherits slots and methods from each of its direct supertypes, and so on.
If a slot name/slot form pair is supplied, the slot form is a form that can be evaluated by 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 implementation-dependent way.
If the type being defined and some other type from which it inherits have a slot by the same name, only one slot is allocated in the 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 defclass.
A description of slot-options follows:
(defmethod print-object ((x c) stream) (if *print-escape* (call-next-method) (report-name x stream)))
If the value supplied by the argument to :report (report-name) is a symbol or a lambda expression, it must be acceptable to function. (function report-name) is evaluated in the current lexical environment. It should return a function of two arguments, a condition and a stream, that prints on the stream a description of the condition. This function is called whenever the condition is printed while *print-escape* is nil.
If report-name is a string, it is a shorthand for
(lambda (condition stream) (declare (ignore condition)) (write-string report-name stream))
This option is processed after the new 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 condition is inherited from the parent-type.
The consequences are unspecifed if an attempt is made to 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 setf.
If a define-condition form appears as a top level form, the compiler must make name recognizable as a valid type name, and it must be possible to reference the condition type as the parent-type of another condition type in a subsequent define-condition form in the file being compiled.
Examples:
The following form defines a condition of type peg/hole-mismatch which inherits from a condition type called blocks-world-error:
(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 (lambda (condition stream)
             (format stream "A ~A peg cannot go in a ~A hole."
                     (peg/hole-mismatch-peg-shape  condition)
                     (peg/hole-mismatch-hole-shape condition)))))
 The new type has slots peg-shape and hole-shape, so make-condition accepts :peg-shape and :hole-shape keywords. The 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 condition type named machine-error which inherits from error:
(define-condition machine-error 
                  (error)
                  ((machine-name :initarg :machine-name
                                 :reader machine-error-machine-name))
  (:report (lambda (condition stream)
             (format stream "There is a problem with ~A."
                     (machine-error-machine-name condition)))))
 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:
(define-condition machine-not-available-error (machine-error) ()
  (:report (lambda (condition stream)
             (format stream "The machine ~A is not available."
                     (machine-error-machine-name condition)))))
 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:
(define-condition my-favorite-machine-not-available-error
                  (machine-not-available-error)
  ((machine-name :initform "mc.lcs.mit.edu")))
 Note that since no :report clause was given, the information inherited from machine-not-available-error is used to report this type of condition.
 (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)))
=>  ATE-TOO-MUCH
 (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 (lambda (condition stream)
              (format stream "~A ate too much ~A ice-cream"
                      (ate-too-much-person condition)
                      (ate-too-much-ice-cream-flavor condition)))))
=>  ATE-TOO-MUCH-ICE-CREAM
 (make-condition 'ate-too-much-ice-cream
                 :person 'fred
                 :weight 300
                 :flavor 'chocolate)
=>  #<ATE-TOO-MUCH-ICE-CREAM 32236101>
 (format t "~A" *)
>>  FRED ate too much CHOCOLATE ice-cream
=>  NIL
 
Affected By: None.
Exceptional Situations: None.
See Also:
make-condition, defclass, Section 9.1 (Condition System Concepts)
Notes: None.
![[Starting Points]](../Graphics/StartPts.gif)
![[Contents]](../Graphics/Contents.gif)
![[Index]](../Graphics/Index.gif)
![[Symbols]](../Graphics/Symbols.gif)
![[Glossary]](../Graphics/Glossary.gif)
![[Issues]](../Graphics/Issues.gif)