Examples of Class Precedence List Determination (ANSI and GNU Common Lisp Document)

Previous: Topological Sorting, Up: Determining the Class Precedence List

#### 4.3.5.2 Examples of Class Precedence List Determination

This example determines a class precedence list for the class `pie`. The following classes are defined:

     (defclass pie (apple cinnamon) ())

     (defclass apple (fruit) ())

     (defclass cinnamon (spice) ())

     (defclass fruit (food) ())

     (defclass spice (food) ())

     (defclass food () ())

The set S_{pie}~= {pie, apple, cinnamon, fruit, spice, food, standard-object, t }. The set R~= { (pie, apple), (apple, cinnamon), (apple, fruit), (cinnamon, spice), \break (fruit, food), (spice, food), (food, standard-object), (standard-object, t) }.

The class `pie` is not preceded by anything, so it comes first; the result so far is `(pie)`. Remove `pie` from S and pairs mentioning `pie` from R to get S~= {apple, cinnamon, fruit, spice, food, standard-object, t } and R~=~{(apple, cinnamon), (apple, fruit), (cinnamon, spice),\break (fruit, food), (spice, food), (food, standard-object), (standard-object, t) }.

The class `apple` is not preceded by anything, so it is next; the result is `(pie apple)`. Removing `apple` and the relevant pairs results in S~= { cinnamon, fruit, spice, food, standard-object, t } and R~= { (cinnamon, spice), (fruit, food), (spice, food), (food, standard-object),\break (standard-object, t) }.

The classes `cinnamon` and `fruit` are not preceded by anything, so the one with a direct subclass rightmost in the class precedence list computed so far goes next. The class `apple` is a direct subclass of `fruit`, and the class `pie` is a direct subclass of `cinnamon`. Because `apple` appears to the right of `pie` in the class precedence list, `fruit` goes next, and the result so far is `(pie apple fruit)`. S~= { cinnamon, spice, food, standard-object, t }; R~= {(cinnamon, spice), (spice, food),\break (food, standard-object), (standard-object, t) }.

The class `cinnamon` is next, giving the result so far as `(pie apple fruit cinnamon)`. At this point S~= { spice, food, standard-object, t }; R~= { (spice, food), (food, standard-object), (standard-object, t) }.

The classes `spice`, `food`, standard-object, and t are added in that order, and the class precedence list is `(pie apple fruit cinnamon spice food standard-object t)`.

It is possible to write a set of class definitions that cannot be ordered. For example:

     (defclass new-class (fruit apple) ())

     (defclass apple (fruit) ())

The class `fruit` must precede `apple` because the local ordering of superclasses must be preserved. The class `apple` must precede `fruit` because a class always precedes its own superclasses. When this situation occurs, an error is signaled, as happens here when the system tries to compute the class precedence list of `new-class`.

The following might appear to be a conflicting set of definitions:

     (defclass pie (apple cinnamon) ())

     (defclass pastry (cinnamon apple) ())

     (defclass apple () ())

     (defclass cinnamon () ())

The class precedence list for `pie` is `(pie apple cinnamon standard-object t)`.

The class precedence list for `pastry` is `(pastry cinnamon apple standard-object t)`.

It is not a problem for `apple` to precede `cinnamon` in the ordering of the superclasses of `pie` but not in the ordering for `pastry`. However, it is not possible to build a new class that has both `pie` and `pastry` as superclasses.

Previous: Topological Sorting, Up: Determining the Class Precedence List