Conditions

A condition is an object whose class indicates the general nature of the condition and whose instance data carries information about the details of the particular circumstances that lead to the condition being signaled.3 In this hypothetical log analysis program, you might define a condition class, malformed-log-entry-error, that parse-log-entry will signal if it’s given data it can’t parse.

Condition classes are defined with the **DEFINE-CONDITION** macro, which works essentially the same as **DEFCLASS** except that the default superclass of classes defined with **DEFINE-CONDITION** is **CONDITION** rather than **STANDARD-OBJECT**. Slots are specified in the same way, and condition classes can singly and multiply inherit from other classes that descend from **CONDITION**. But for historical reasons, condition classes aren’t required to be instances of **STANDARD-OBJECT**, so some of the functions you use with **DEFCLASS**ed classes aren’t required to work with conditions. In particular, a condition’s slots can’t be accessed using **SLOT-VALUE**; you must specify either a :reader option or an :accessor option for any slot whose value you intend to use. Likewise, new condition objects are created with **MAKE-CONDITION** rather than **MAKE-INSTANCE**. **MAKE-CONDITION** initializes the slots of the new condition based on the :initargs it’s passed, but there’s no way to further customize a condition’s initialization, equivalent to **INITIALIZE-INSTANCE**.4

When using the condition system for error handling, you should define your conditions as subclasses of **ERROR**, a subclass of **CONDITION**. Thus, you might define malformed-log-entry-error, with a slot to hold the argument that was passed to parse-log-entry, like this:

  1. (define-condition malformed-log-entry-error (error)
  2. ((text :initarg :text :reader text)))