From: Jim Newton
Subject: before after methods and call-next-method
Date: 
Message-ID: <2imsh6Fp1q89U1@uni-berlin.de>
I am wondering why call-next-method is specified to work the way
it does with regard to before and after methods.  It seems to me
that it works counter-intuitive.  I am quite new to CLOS so i
hope i have the syntax correct.

For example.

(defclass a nil nil)
(defclass b ( a ) nil)

(defmethod x :before (( b b))  ;; meth 2
    some...setup... )

(defmethod x (( a a ))  ;; meth 1
    some...primary...)

(x (make-instance 'b))  ;; calls meth 2 then meth 1

Now if i do not know the implementation of x, and i
define a subclass of b


(defclass c ( b ) nil)

(defmethod x (( c c))
    (+ (something ...)
       (call-next-method)))

I would expect that call-next-method in this case
would mimmic the behavior of calling x on an instance
of b.  But it apparently does not.
In fact #meth 2 does not get called.  At least that is
my understanding.

I know I could define a subclass of std-method (or whatever its name is)
and define my generic function to use that meta-class, but it seems
to me that I should not have to know how x is implimented in
in order to add some additional functionality in a subclass.

Does this functionality of call-next-method bother anyone
else besides me?

-jim

From: Kenny Tilton
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <bqrxc.170056$WA4.48713@twister.nyc.rr.com>
Jim Newton wrote:
> I am wondering why call-next-method is specified to work the way
> it does with regard to before and after methods.  It seems to me
> that it works counter-intuitive.  I am quite new to CLOS so i
> hope i have the syntax correct.
> 
> For example.
> 
> (defclass a nil nil)
> (defclass b ( a ) nil)
> 
> (defmethod x :before (( b b))  ;; meth 2
>    some...setup... )
> 
> (defmethod x (( a a ))  ;; meth 1
>    some...primary...)
> 
> (x (make-instance 'b))  ;; calls meth 2 then meth 1
> 
> Now if i do not know the implementation of x, and i
> define a subclass of b
> 
> 
> (defclass c ( b ) nil)
> 
> (defmethod x (( c c))
>    (+ (something ...)
>       (call-next-method)))
> 
> I would expect that call-next-method in this case
> would mimmic the behavior of calling x on an instance
> of b.  But it apparently does not.
> In fact #meth 2 does not get called.  At least that is
> my understanding.

No, that is wrong. Review: Around methods go first in decreasing order 
of specificity, then the before methods in decreasing order of 
specificity, then the primary, then the afters in increasing order of 
specificity.

So I wager what you call method 2 is called before you hit the primary, 
which will be for class C, and then call-next-method hits the primary 
for class B.

You can get the order you seem to want by making the primary method 
specialized on C into an around method. Then it will run first and 
call-next-method will run the before method on B and then the primary 
method on A.

kenny
From: Kenny Tilton
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <jurxc.170057$WA4.24072@twister.nyc.rr.com>
Kenny Tilton wrote:

> 
> 
> Jim Newton wrote:
> 
>> I am wondering why call-next-method is specified to work the way
>> it does with regard to before and after methods.  It seems to me
>> that it works counter-intuitive.  I am quite new to CLOS so i
>> hope i have the syntax correct.
>>
>> For example.
>>
>> (defclass a nil nil)
>> (defclass b ( a ) nil)
>>
>> (defmethod x :before (( b b))  ;; meth 2
>>    some...setup... )
>>
>> (defmethod x (( a a ))  ;; meth 1
>>    some...primary...)
>>
>> (x (make-instance 'b))  ;; calls meth 2 then meth 1
>>
>> Now if i do not know the implementation of x, and i
>> define a subclass of b
>>
>>
>> (defclass c ( b ) nil)
>>
>> (defmethod x (( c c))
>>    (+ (something ...)
>>       (call-next-method)))
>>
>> I would expect that call-next-method in this case
>> would mimmic the behavior of calling x on an instance
>> of b.  But it apparently does not.
>> In fact #meth 2 does not get called.  At least that is
>> my understanding.
> 
> 
> No, that is wrong. Review: Around methods go first in decreasing order 
> of specificity, then the before methods in decreasing order of 
> specificity, then the primary, then the afters in increasing order of 
> specificity.
> 
> So I wager what you call method 2 is called before you hit the primary, 
> which will be for class C, and then call-next-method hits the primary 
> for class B.

should be "the primary for class A".

> 
> You can get the order you seem to want by making the primary method 
> specialized on C into an around method. Then it will run first and 
> call-next-method will run the before method on B and then the primary 
> method on A.
> 
> kenny
> 

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Joe Marshall
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <r7spwt8t.fsf@comcast.net>
Jim Newton <·····@rdrop.com> writes:

> I am wondering why call-next-method is specified to work the way
> it does with regard to before and after methods.  It seems to me
> that it works counter-intuitive.  I am quite new to CLOS so i
> hope i have the syntax correct.
>
> For example.
>
> (defclass a nil nil)
> (defclass b ( a ) nil)
>
> (defmethod x :before (( b b))  ;; meth 2
>     some...setup... )
>
> (defmethod x (( a a ))  ;; meth 1
>     some...primary...)
>
> (x (make-instance 'b))  ;; calls meth 2 then meth 1
>
> Now if i do not know the implementation of x, and i
> define a subclass of b
>
>
> (defclass c ( b ) nil)
>
> (defmethod x (( c c))
>     (+ (something ...)
>        (call-next-method)))
>
> I would expect that call-next-method in this case
> would mimmic the behavior of calling x on an instance
> of b.  But it apparently does not.
> In fact #meth 2 does not get called.  At least that is
> my understanding.

Are you using an implementation where this is the case?

Conceptually, when X is called on an instance of C, we first find all
the applicable methods.  There are three: (:before b), (:primary a),
and (:primary c).  These are combined so that the before methods run,
then the most specific primary method, then the after methods.  So I'd
expect the (:before b) method, then the (:primary c), and within the
(:primary C), the (:primary A).

CL-USER 16 > (defclass a nil nil)
#<STANDARD-CLASS A 205F61DC>

CL-USER 17 >  (defclass b ( a ) nil)
#<STANDARD-CLASS B 205F7C5C>

CL-USER 18 > (defmethod x :before (( b b))
 (format t "~&Before method B called."))
#<STANDARD-METHOD X (:BEFORE) (B) 205F460C>

CL-USER 19 > (defmethod x (( a a))
  (format t "~&Primary method a called.") 42)
#<STANDARD-METHOD X NIL (A) 205F6474>

CL-USER 20 >  (defclass c ( b ) nil)
#<STANDARD-CLASS C 20602E8C>

CL-USER 21 > (defmethod x (( c c))
  (format t "~&Primary method c called.") (+ 69 (call-next-method)))
#<STANDARD-METHOD X NIL (C) 205F6D64>

CL-USER 22 > (defvar *my-object* (make-instance 'c))
*MY-OBJECT*

CL-USER 23 > (x *my-object*)
Before method B called.
Primary method c called.
Primary method a called.
111

This is the expected behavior.

> Does this functionality of call-next-method bother anyone
> else besides me?

The behavior you describe would indeed bother me.

-- 
~jrm
From: Jim Newton
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <2inmjlFpkbcvU1@uni-berlin.de>
wow, every time i think i understand this, i find out that
my understanding is fatally flawed.

i was under the (apparently false) impression that all
the applicable before and primary methods were sorted from
most specified to least specific and all the befores
were called leading up to and including the primary
method.  But you are saying that ALL the applicable before
methods get called every time even if they are less specific
than the primary method.

So the normal dispatch calls all the applicable before methods
every time?  Then the most specific primary method, then
all the applicable after methods (in reverse order).

I don't think i'm dense, with all the books i've read on
this topic i really never understood that simple fact until
now.

I'm going to go back and read Graham, and Keenes, and
Kiczales again-again and see where I was blind before.

-jim

Joe Marshall wrote:
> Jim Newton <·····@rdrop.com> writes:
> 
> 
>>I am wondering why call-next-method is specified to work the way
>>it does with regard to before and after methods.  It seems to me
>>that it works counter-intuitive.  I am quite new to CLOS so i
>>hope i have the syntax correct.
>>
>>For example.
>>
>>(defclass a nil nil)
>>(defclass b ( a ) nil)
>>
>>(defmethod x :before (( b b))  ;; meth 2
>>    some...setup... )
>>
>>(defmethod x (( a a ))  ;; meth 1
>>    some...primary...)
>>
>>(x (make-instance 'b))  ;; calls meth 2 then meth 1
>>
>>Now if i do not know the implementation of x, and i
>>define a subclass of b
>>
>>
>>(defclass c ( b ) nil)
>>
>>(defmethod x (( c c))
>>    (+ (something ...)
>>       (call-next-method)))
>>
>>I would expect that call-next-method in this case
>>would mimmic the behavior of calling x on an instance
>>of b.  But it apparently does not.
>>In fact #meth 2 does not get called.  At least that is
>>my understanding.
> 
> 
> Are you using an implementation where this is the case?
> 
> Conceptually, when X is called on an instance of C, we first find all
> the applicable methods.  There are three: (:before b), (:primary a),
> and (:primary c).  These are combined so that the before methods run,
> then the most specific primary method, then the after methods.  So I'd
> expect the (:before b) method, then the (:primary c), and within the
> (:primary C), the (:primary A).
> 
> CL-USER 16 > (defclass a nil nil)
> #<STANDARD-CLASS A 205F61DC>
> 
> CL-USER 17 >  (defclass b ( a ) nil)
> #<STANDARD-CLASS B 205F7C5C>
> 
> CL-USER 18 > (defmethod x :before (( b b))
>  (format t "~&Before method B called."))
> #<STANDARD-METHOD X (:BEFORE) (B) 205F460C>
> 
> CL-USER 19 > (defmethod x (( a a))
>   (format t "~&Primary method a called.") 42)
> #<STANDARD-METHOD X NIL (A) 205F6474>
> 
> CL-USER 20 >  (defclass c ( b ) nil)
> #<STANDARD-CLASS C 20602E8C>
> 
> CL-USER 21 > (defmethod x (( c c))
>   (format t "~&Primary method c called.") (+ 69 (call-next-method)))
> #<STANDARD-METHOD X NIL (C) 205F6D64>
> 
> CL-USER 22 > (defvar *my-object* (make-instance 'c))
> *MY-OBJECT*
> 
> CL-USER 23 > (x *my-object*)
> Before method B called.
> Primary method c called.
> Primary method a called.
> 111
> 
> This is the expected behavior.
> 
> 
>>Does this functionality of call-next-method bother anyone
>>else besides me?
> 
> 
> The behavior you describe would indeed bother me.
> 
From: Joe Marshall
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <8yewwyix.fsf@ccs.neu.edu>
Jim Newton <·····@rdrop.com> writes:

> wow, every time i think i understand this, i find out that
> my understanding is fatally flawed.
>
> i was under the (apparently false) impression that all
> the applicable before and primary methods were sorted from
> most specified to least specific and all the befores
> were called leading up to and including the primary
> method.  But you are saying that ALL the applicable before
> methods get called every time even if they are less specific
> than the primary method.

Yes.

> So the normal dispatch calls all the applicable before methods
> every time?  Then the most specific primary method, then
> all the applicable after methods (in reverse order).

Yes.  And the around methods go around the whole thing (the most
specific :around method is the very first thing called, if it invokes
call-next-method, that invokes the next most specific :around method
until you get to the least specific :around method.  If the least
specific :around method invokes call-next-method, then you start
executing the :before methods, the primary, and the :after methods.

See section 7.6.6.2 of the Hyperspec.

> I don't think i'm dense, with all the books i've read on
> this topic i really never understood that simple fact until
> now.

It took me a while to get it, too.  I don't know why because now it
seems dead simple.
From: Jim Newton
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <2iroaaFqkkjnU1@uni-berlin.de>
so is it true that if i put an around method around
a method on a base class and do not call call-next-method
within that around method then i disable all before,
after, and primary methods of all subclasses?

-jim

Joe Marshall wrote:
> Jim Newton <·····@rdrop.com> writes:
> 
> 
>>wow, every time i think i understand this, i find out that
>>my understanding is fatally flawed.
>>
>>i was under the (apparently false) impression that all
>>the applicable before and primary methods were sorted from
>>most specified to least specific and all the befores
>>were called leading up to and including the primary
>>method.  But you are saying that ALL the applicable before
>>methods get called every time even if they are less specific
>>than the primary method.
> 
> 
> Yes.
> 
> 
From: Joe Marshall
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <4qpjte16.fsf@ccs.neu.edu>
Jim Newton <·····@rdrop.com> writes:

> so is it true that if i put an around method around
> a method on a base class and do not call call-next-method
> within that around method then i disable all before,
> after, and primary methods of all subclasses?

Yes.  Around methods can be used as *BIG* sledgehammers if the need
arises.
From: Pascal Costanza
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <caaafe$1bi$1@newsreader2.netcologne.de>
Jim Newton wrote:

> so is it true that if i put an around method around
> a method on a base class and do not call call-next-method
> within that around method then i disable all before,
> after, and primary methods of all subclasses?

Yes. But it's generally a good idea to make your own methods specialize 
on at least one of your own classes, unless the documentation for some 
generic function explicitly allows you to be more general. Otherwise you 
risk that you replace some other important method. (Of course, you are 
allowed to do anything when you exactly know what you do...)


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Kenny Tilton
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <biFxc.171598$WA4.23548@twister.nyc.rr.com>
Jim Newton wrote:
> So the normal dispatch calls all the applicable before methods
> every time?  Then the most specific primary method, then
> all the applicable after methods (in reverse order).
> 
> I don't think i'm dense, with all the books i've read on
> this topic i really never understood that simple fact until
> now.
> 
> I'm going to go back and read Graham, and Keenes, and
> Kiczales again-again and see where I was blind before.

Reading may not help if the books just tell you the order. I think CLOS 
(like the rest of CL) works exactly the way one would like, and 
understanding how that is so makes it easier (for me, anyway) to 
remember the details when I have to sweat the order of execution.

Think of before methods as "preparation" or "set-up", and after methods 
as "mop-up". Not that these are the only things they can be used for, 
but just as typical applications of before/after. This

OK, so you have class A and you know it needs some mop-up, so you write 
an after method to do the mop-up. Now you subclass A. That subclass 
still needs the mop-up! And you do not want it to run before the primary 
methods have been run, because as a mop-up it is probably releasing some 
resource or something like that. Likewise with "set-up" code--it's gotta 
run before any primary business is undertaken.

I play the same game with why befores and arounds start with the most 
specific and afters end with the most specific. The name "around" makes 
it easy to remember they get first crack at a GF and can even shadow all 
the other processing by not calling call-next-method.

kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Barry Margolin
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <barmar-17E696.12132609062004@comcast.dca.giganews.com>
In article <······················@twister.nyc.rr.com>,
 Kenny Tilton <·······@nyc.rr.com> wrote:

> Think of before methods as "preparation" or "set-up", and after methods 
> as "mop-up". Not that these are the only things they can be used for, 
> but just as typical applications of before/after. This
> 
> OK, so you have class A and you know it needs some mop-up, so you write 
> an after method to do the mop-up. Now you subclass A. That subclass 
> still needs the mop-up! And you do not want it to run before the primary 
> methods have been run, because as a mop-up it is probably releasing some 
> resource or something like that. Likewise with "set-up" code--it's gotta 
> run before any primary business is undertaken.

They are also heavily used in "mixin-style" programming, and this should 
help understand why the auxiliary methods for less-specific classes are 
always run.  Mixin classes typically do all their work in :BEFORE, 
:AFTER, or :AROUND methods so that their behavior augments that of the 
classes they're being mixed with.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Peter Seibel
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <m33c55y4d1.fsf@javamonkey.com>
Jim Newton <·····@rdrop.com> writes:

> I am wondering why call-next-method is specified to work the way
> it does with regard to before and after methods.  It seems to me
> that it works counter-intuitive.  I am quite new to CLOS so i
> hope i have the syntax correct.
>
> For example.
>
> (defclass a nil nil)
> (defclass b ( a ) nil)
>
> (defmethod x :before (( b b))  ;; meth 2
>     some...setup... )
>
> (defmethod x (( a a ))  ;; meth 1
>     some...primary...)
>
> (x (make-instance 'b))  ;; calls meth 2 then meth 1
>
> Now if i do not know the implementation of x, and i
> define a subclass of b
>
>
> (defclass c ( b ) nil)
>
> (defmethod x (( c c))
>     (+ (something ...)
>        (call-next-method)))
>
> I would expect that call-next-method in this case
> would mimmic the behavior of calling x on an instance
> of b.  But it apparently does not.
> In fact #meth 2 does not get called.  At least that is
> my understanding.

It does not get called by CALL-NEXT-METHOD because it has already run
by the time the primary method specialized on C runs.

> I know I could define a subclass of std-method (or whatever its name
> is) and define my generic function to use that meta-class, but it
> seems to me that I should not have to know how x is implimented in
> in order to add some additional functionality in a subclass.

Well the point of the standard method combination is to split up the
implementation of X into four parts each of which plays a different
role. But this does require folks who want to extend X to understand
some of how it is split up.

> Does this functionality of call-next-method bother anyone
> else besides me?

I know where you're coming from--it seems a bit strange that when you
define a new primary method on X specialized on class C that part of
the existing implementation--parts specialized on less-specific
classes--will run before your new method. Probably the best way to
think about it is to think of how you would implement exactly the same
behavior with only primary methods. You could do it by coding
convention: for each GF, X, define five GF's before-x, after-x,
around-x, primary-x, and x. Then write all the methods on those GFs
using the following pattern:

  (defmethod before-x ((obj foo))
    ;; do stuff for this class
    (call-next-method))

  (defmethod after-x ((obj foo))
    (call-next-method)
    ;; do stuff for this class
    )

  (defmethod around-x ((obj foo))
    ;; stuff for this class
    (multiple-value-prog1
      (maybe-frob-result-for-this-class 
        (cond 
         ((next-method-p) (call-next-method))
         (t
           (before-x foo)
           (multiple-value-prog1
             (primary-x foo)
             (after-x foo)))))
      ;; more stuff for this class
      ))

  (defmethod primary-x ((obj foo))
    ;; stuff for this class, perhaps with a CALL-NEXT-METHOD
    )

Then the actual X is defined as:

  (defmethod x ((obj foo)) (around-x foo))

By following this coding convention you get the same results as the
standard method combination: the before-x methods run the code for the
more-specific class first and then call up to less-specific methods
while after-x methods let the less-specific methods run first. Andthe
around-x methods do their thing with the primary-x methods actually
generating the result. If you don't want the functionality for x split
up this way then you probably just want to use primary methods.

Hmmm. I'm not sure if that'll help or not. Maybe.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Peter Seibel
Subject: Re: before after methods and call-next-method
Date: 
Message-ID: <m3k6yhwdjj.fsf@javamonkey.com>
Jim Newton <·····@rdrop.com> writes:

> I am wondering why call-next-method is specified to work the way it
> does with regard to before and after methods. It seems to me that it
> works counter-intuitive.

Here's another way to think about the standard-method-combination that
may be helpful if you're used to thinking in terms of invariants such
as preconditions and postconditions.[1]

Start from a generic function. The gf defines an operation in the
abstract. For simplicity let's assume it takes only one argument so we
don't have to deal with the possibility of multimethods though this
way of thinking about methods can be extended to multimethods without
any real problem.

If we think of the generic function in terms of invariants we can
specify the precondition--the set of things that must be true before
we can call the generic function--and the postcondition--the set of
things that will be true after the function returns. The contract of
the generic function is that if the precondition is met before it is
called, then the postcondition will be true if the function returns.
Thinking of a generic function this way is useful because it makes it
quite clear to a potential caller of the gf when it can be used and
what they can count on if they do call it. Conversely, it also sets up
the rules for anyone who wants to implement the gf.

For simplicity, let's assume that all the elements of the precondition
are statements about the state of the object that will be passed to
the gf and the elements of the postcondition are statements about the
subsequent state of the argument object and about the return value of
the function.

Now suppose we implement a primary method that implements the generic
function for some base class, A. Assuming the method is a correct
implementation of the gf, if it is the effective method for a given
call to the gf with the precondition satisfied it will achieve the
gf's postcondition.

Now assume that there are subclasses of A; B subclasses A and C
subclasses B.. We can define new methods for our gf that specialize on
these subclasses.

According to the logic of invariants, the same operation invoked on a
more specific class can loosen the precondition--expect less from the
caller--and can tighten the postcondition--promise more. For instance,
suppose our gf computes a value based on the value of some slot and
the precondition requires that the value reflect other operations that
have been performed on the object.

Now suppose that in class B, the value of that slot is maintained
lazily--at any given instant its value may not be up to date. We could
define a method that implements our gf specializing on B that loosens
the precondition that the slot value be up to date as long as the new
method brings the value up to date before performing the computation.
If we were just using primary methods we could write a method like
this:

  (defmethod foo ((obj b))
    (update-the-slot obj)
    (call-next-method))

In other words, the method specialized on B can be used when the
original precondition is not met as long is it establishes the
precondition before calling CALL-NEXT-METHOD.

Now suppose we (or perhaps another programmer) want to implement a
method specializing on C (the subclass of B). In this case suppose we
are going to completely replace the implementation of the gf, not
calling CALL-NEXT-METHOD. What can we assume about the precondition
that will hold when the gf is called? Well, since a C is a subclass of
B and the method specialized on B has loosened the precondition we
can't tighten it back up. This is because some innocent caller may
have an object which is actually a C but they only know is a B.
Knowing the rules for when they are allowed to invoke the gf with a B
they might call it with only the looser B-method precondition
satisfied. But that call will end up in our C-specialized method so it
has to work in that situation.

So the author of the C-specialized method has to play by the new rules
set up by the author of the B-specialized method. Which isn't crazy
since C is a subclass of B.

However the standard method combination gives us another choice. If
instead of a new primary method specialized on B, we had written a
:before method like this:

  (defmethod foo :before ((obj b))
    (update-the-slot obj))

then the new primary method specialized on C can be written assuming
the original precondition will be met because by the time the primary
method runs the :before method specialized on B will have run and had
a chance to establish the original precondition.

Now suppose class D subclasses C and that we want to allow the gf to
be called with a D instance with an even looser precondition than the
loosened precondition allowed when the argument is a B. We can define
a :before method specialized on D that accepts the even looser
precondition and establishes the B precondition, knowing that the
:before method on B will take us the rest of the way to the original
precondition before the primary method runs.

The :after methods in the standard method combination play a analogous
role with respect to the postcondition. Primary methods will be
responsible for establishing the original gf postcondition but we are
allowed to tighten the postcondition when implementing the gf for
specific classes--a caller of the gf who passes a B may be able to
count on specific B-specific state changes having taken place that
aren't part of the general contract of the gf. Since :after methods
runs from least- to most-specific each :after method will run after
the primary method has established the original postcondition and
after all less specific :after methods have established any tighter
postconditions.

To sum up, if we use :before, :after and primary methods this way when
we write a primary method we need only consider the original pre- and
postconditions documented for the gf. We can use :before methods to
loosen the precondition by writing methods that takes us from the
looser precondition to that of the next most specific :before method
or, in the least-specific :before method, that of the gf. And we can
write :after methods that establish tighter postconditions while
relying on the postconditions established by the primary method and
any less-specific :after methods.

-Peter

[1] If not, you may want to check out Bertrand Meyer's writings on
Design By Contract.


-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp