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
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
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