Over the last few days, I've checked in code which I think improves
the handling of a corner of the MOP: subclasses of SPECIALIZER that
are not provided by the implementation. As ever with modifications to
PCL, it's a bit of a scary business and I'm not completely convinced
that I've covered all the ways in which things could possibly go
wrong, so testing with care would be much appreciated -- if any
anomalies surface in ordinary CLOS code, that would be worth knowing
sooner rather than later.
The fixes I've committed allow users to define methods with
non-standard specializers on generic functions of non-standard class.
In order to do so, either COMPUTE-APPLICABLE-METHODS and
COMPUTE-APPLICABLE-METHODS-USING-CLASSES must both be overridden for
that generic function class, as the standard methods must signal an
error if any specializer is non-standard; or
COMPUTE-DISCRIMINATING-FUNCTION must be overridden for that generic
function class so as not to call
COMPUTE-APPLICABLE-METHODS(-USING-CLASSES) in the first place.
At present, there is no surface syntax for this, and the specializer
must appear literally in the defmethod form, like
(let ((spec (make-magic-specializer ...)))
(eval `(defmethod foo ((x ,spec)) ...)))
[ maybe a PARSE-SPECIALIZER-NAME(-USING-CLASS)? function would be a
worthwhile addition to SB-PCL? ]. Additionally, for the purposes
of FIND-METHOD, the system considers specializers which are EQL to be
the same specializer (and those which are not EQL to be different);
again, there is maybe a case for exporting SAME-SPECIALIZER-P for
users to customize for their own specializer classes. I think that
these are the only two warts...
Examples of this functionality can be seen in the new test files
which respectively contain a minmal test of a
non-standard-but-PCL-supported specializer (CLASS-EQ), a simple-minded
implementation of a pattern-dispatching generic function class, and an
implementation of a specializer representing a disjunction of classes.
I hope that they can be used as templates for more interesting cases
-- extending the pattern-dispatching example to something which
compiles the discrimination on-the-fly, adjusting based on dynamic
calling information, would make an excellent little project for the
enthusiast, for example; similarly, testing out strategies for
predicate dispatch should be possible.