[comp.lang.clos] CLOS method combination

Hornig@riverside.scrc.symbolics.com (Charles Hornig) (06/26/91)

    Date: Wed, 26 Jun 1991 03:15 EDT
    From: barmar@think.com (Barry Margolin)

    References <LGM.91Jun25201133@cbnewsc.ATT.COM>, <9106260502.AA11848@kuwait>, <42474@ucbvax.BERKELEY.EDU>
    Reply-To : barmar@think.com
    Subject : Re: CLOS Private Methods

    In article <42474@ucbvax.BERKELEY.EDU> konstan@elmer-fudd.berkeley.edu (Joe Konstan) writes:
    >Re:  Encapsulation and fear of packages
    >
    >I think that the lack of encapsulation problem is more than merely a fear of
    >packages.  With CLOS, there are many cases where a useful functionality is
    >unavailable unless you have (and can modify) the source code to a class and/or
    >the methods which specialize on that class.  For one example ...

    >(defmethod CLEAN ((self HOUSE))
    >  (wash-windows self)
    >  (scrub-floors self))
    >
    >(defmethod CLEAN ((self BOAT))
    >  (scrape-barnacles self))		;; I show my ignorance about boats
    >
    >The default behavior I want for HOUSEBOAT is to do both.  I can't do this by
    >not defining a method, since neither HOUSE not BOAT does a call-next-method
    >and therefore only the first superclass will have its method called.

Here is one possibility:

(defgeneric CLEAN (thing)
  (:method-combination progn))

(defmethod CLEAN progn ((self HOUSE))
  (wash-windows self)
  (scrub-floors self))

(defmethod CLEAN progn ((self BOAT))
  (scrape-barnacles self))		;; I show my ignorance about boats

Note that boats and houses do not have to know about each other.

konstan@elmer-fudd.berkeley.edu (Joe Konstan) (06/27/91)

I'm not sure I made my houseboat problem clear enough in my first posting.
I've seen three postings and some E-mail suggesting either designing the CLEAN
methods to call-next-method (when one is available) or designing CLEAN as a
generic function with method-combination type progn.  This is why I feel that
neither of these is an acceptable solution:

1.	First and foremost, these require that HOUSE and BOAT be assured that
no superclass of theirs ever has a CLEAN method defined.  In fact, I might
very well have defined HOUSE as a subclass of BUILDING and RESIDENCE where
BUILDING has a CLEAN method defined on it which should NOT be used by HOUSE.
As a result, HOUSE's CLEAN cannot (call-next-method) as this will call in the
janitors to clean the BUILDING.  Further, CLEAN cannot use method-combination
type progn since I may have defined BOAT as a subclass of SEA-VESSEL and
some other class where I want to inherit CLEAN using standard method
combination.

2.	Since I am not provided with the source code, I consider it
unreasonable to implement any solution (such as the progn solution) that
requires changing the methods themselves.

Here is what I would consider an adequate solution (or at least a good start):

1.	Let each method have its own method-combination type used to determine
how to interpret call-next-method among its inherited methods (i.e., the
superclasses).

2.	In this case, the method-combination type for HOUSEBOAT could be
progn, but the method-combination types for HOUSE and for BOAT could be
completely different and should not matter.  What matters is that I, as the
creator of the HOUSEBOAT class, can decide that I want to do both the HOUSE
and BOAT operations for CLEAN.

3.	This is clearly harder to optimize and needs to be better defined with
respect to the execution order when :around, :before, and :after methods are
added in, but I think it is workable.

I'm not disputing the claim that a complete system can be designed well so
these problems do not arise.  I don't think this is adequate, however, since
designing a system well in CLOS is hard, and most of the code we would like to
borrow from others will not have been designed well.  As a result, the
language must support techniques for getting the most out of existing classes
and methods without modifying their source code.

Joe Konstan
konstan@cs.berkeley.edu