Re: class precedence list

From: Erick Gallesio <Erick.Gallesio_at_unice.fr>
Date: Wed, 13 Oct 1999 10:34:08 +0200 (CEST)

Anthony Beurive' writes:
>
> I got a problem with class precedence. I will simplify the problem
> for clarity. Consider the following class definitions:
>
> (define-class <A> () ())
> (define-class <B> (<A>) ())
> (define-class <C> (<A>) ())
> (define-class <D> (<B>) ())
> (define-class <E> (<C>) ())
> (define-class <F> (<D> <E>) ())
>
> The class precedence list of <F> resulting of a call to
> class-precedence-list gives the following: (<F> <D> <E> <B> <A> <C>).
> I believe this brakes the first rule of class precedence given in the
> reference manual p. 87: "Each class is more specific than its
> superclasses." Obviously, <C> is more specific than <A>, but it
> appears later.

Oops, that's true. It seems that there is a problem here.

>
> Is it a well-known problem of class precedence in STklos or CLOS? I
> must admit I'm new to this kind of problems.

The class precedence list computation of CLOS and STklos are
completely different. CLOS algorithm is rather complicated and not
always satisfying (imho). STklos algorithm tries to work "by
level". Your inheritance is

        A
       / \
     B C
     | |
     D E
      \ /
        F

so it should be F D E B C A. I know that CLOS gives something different
but after all this is a matter of conventions. BTW, the algorithm to
compute the cpl is simply

    (define (compute-cpl class)

      (define (filter-cpl class)
        (let ((res '()))
          (for-each (lambda (item)
                      (unless (or (eq? item <object>)
                                  (eq? item <top>)
                                  (member item res))
                       (set! res (cons item res))))
                  class)
          res))

      (let* ((supers (slot-ref class 'direct-supers))
             (big-list (apply append (cons class supers)
                       (map compute-cpl supers))))
        (reverse (list* <top> <object> (filter-cpl big-list)))))

whereas it is a 80 lines algorithm for Tiny CLOS. BTW, I have just
re-read this function now and I must admit that it is not too pretty.

>
> I can see two solutions that don't really satisfy me. The first one
> is <B> not to inherit from <A>.

This is probably the wrong solution. I suppose that if <B> inherit of
<A> you have strong reasons for that, and you hierarchical
decomposition should not be changed.


>The second is to explicitly specify
> the class precedence list of <F>: (define-class <F> (<D> <E> <B> <C>)
> ()) or (define-class <F> (<D> <E> <B> <C> <A>) ()). Do other
> solutions exist?

This is imho the right solution IN GENERAL. As I said before, the cpl
is a set of conventions and if these conventions are not correct for your
problem, you can always fix it by explicitly give the cpl you want.

The problem HERE is that my function is buggy. I had no time to fix it
right now (but if you have a corrected version I would be happy to
know it ;-)

> Maybe I should modify the class-precedence-list
> procedure?

In CLOS, the class precedence list computation is done by a method,
and you can change it easily. Here you'll have to change it for all
the classes. This is probably cleaner than the STklos approach, but as
I said before, you can always fix the CPL as needed and it seemed to
me that it was a too complicated mechanism for our light OO.


                -- Erick
Received on Wed Oct 13 1999 - 10:34:37 CEST

This archive was generated by hypermail 2.3.0 : Mon Jul 21 2014 - 19:38:59 CEST