From: Paul Tarvydas
Subject: "don't care" method
Date: 
Message-ID: <aZfz8.43924$Il1.5182@news02.bloor.is.net.cable.rogers.com>
Just checking to see if there's a better way to do the following:

I've got two classes, A and B.

Class A has a slot "b-slot" that *sometimes* contains things of type B.
Often, A doesn't have a B associated with it at all, so I've left "b-slot"
initialized to nil.

I need to write code that dereferences the two levels, i.e. (some-b-slot
(b-slot a)).  In the cases where the b-slot of a is nil, I, of course, get
an error.

The only reason that I leave the b-slot initialized to nil is the perverse
sense that I'll save space / conses if I don't create empty B's.

I can solve my problem by:

a) Wrapping ad-hoc logic around the double deref, e.g. (when (b-slot a)
(some-slot (b-slot a)).

b) I can initialize every instance of A with a hollow B.  I could even
optimize this by creating a single global that contains a hollow B, and
initializing every instance of A with the same hollow B.  Real B's would
simply override the initialization.

c) I could write a function or macro to replace "some-b-slot", and check for
nil before trying the second dereference.

I don't know CLOS well enough to know whether this is a stupid question - is
there some way to declare a generic method "some-b-slot" that accepts all
types of arguments and re-dispatches the method call if the argument is nil?

Any other variations?

thanx
pt

From: Kenny Tilton
Subject: Re: "don't care" method
Date: 
Message-ID: <3CCD95A1.56300AA9@nyc.rr.com>
Paul Tarvydas wrote:
> I don't know CLOS well enough to know whether this is a stupid question - is
> there some way to declare a generic method "some-b-slot" that accepts all
> types of arguments and re-dispatches the method call if the argument is nil?

Yes, just specialize on null:

  (defmethod some-b-slot ((missing null))
     <redispatch logic>)

..or you could:

  (defmethod some-b-slot :around (self)
    (if self
       (call-next-method)
       <redispatch>)))

Trouble is you now get this behavior anytime you go after some-b-slot
with nil, not just when a has no b. So maybe it is better to abstract
things a little:

(defmethod some-b-slotish-quality ((self b))
   (some-b-slot b))
(defmethod some-b-slotish-quality ((self a))
   (if (b a) (some-b-slotish-quality b) (some-thing-else a)))

Or simply:
(defmethod some-b-slot ((self a))
   (if (b a)
     (some-b-slot (b a))
     (some-thing-else a)))

...but, depending on the slot, it might be bogus to pretend a has that
attribute. If so, I would say work out what some-b-slotish-quality both
a and b could reasonably have and go that way.


-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Kenny Tilton
Subject: Re: "don't care" method
Date: 
Message-ID: <3CCD967E.41E350DB@nyc.rr.com>
Kenny Tilton wrote:
> 
> Paul Tarvydas wrote:
> > I don't know CLOS well enough to know whether this is a stupid question - is
> > there some way to declare a generic method "some-b-slot" that accepts all
> > types of arguments and re-dispatches the method call if the argument is nil?
> 
> Yes, just specialize on null:
> 
>   (defmethod some-b-slot ((missing null))
>      <redispatch logic>)

of course the other problem here is that you no longer have a reference
to the instance of A to help you with the redispatch, and usually that
is how these things work. but not always...for example, you might just
return nil or some other constant or a global.

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd