[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: specializer metaobjects

  Fake-Sender: gregor@parc.xerox.com
  X-NS-Transport-ID: 08002008D0FD0003D6A3
  Date:	Sun, 4 Nov 1990 14:47:53 PST
  From:	Gregor Kiczales <Gregor@parc.xerox.COM>
  Subject: specializer metaobjects
  To:	mop.PARC@xerox.com
  In the current metaobject protocol is that EQL specializers are not
  objects (with their own special class).  Aside from being conceptually
  gross, this leads to a number of problems.  There are several methods
  that, in a silly way, are specialized to CONS.  It also means that the
  MOP doesn't point the way for users who want to add a new kind of
  specializer.  It doesn't make it clear that they should add a new kind
  of object for the new specializers rather than, for example, further
  overloading CONS.


  Here is some naive model implementation code:
  (defclass class (specializer) ..)
  (defun intern-class-specializer (class-name)
    (find-class class-name))
  (defclass eql-specializer (specializer)
       ((object :initarg :object
                :reader eql-specializer-object)))
  (defvar *eql-specializers* (make-hash-table :test #'eql))
  (defun intern-eql-specializer (object)
    (or (gethash object *eql-specializers*)
        (setf (gethash object *eql-specializers*)
              (make-instance 'eql-specializer :object object))))
  So, a defmethod form and expansion would be something like:
    (defmethod foo ((x foo) (y (eql bar))) ..)
       (make-instance 'standard-method
         :specializers (list (intern-class-specializer 'foo)
                             (intern-eql-specializer bar))
Defmethod should really by written in terms of a gf like:

 (intern-specialize specializer)

(defmethod intern-specializer ((s symbol))
  (find-class s))


  Note that the intern-xxx functions will have to be specified in order to
  allow users to do anonymous creation of methods with EQL specializers.
  If the user wants to do something like the slot class specializers
  discussed at the CLOS workshop they would do:
  (defclass slot-class-specializer (specializer)
       ((slot-name :initarg :slot-name ..)
        (class     :initarg :class     ..)))
  (defvar *slot-class-specializers* (make-hash-table :test #'equal))
  (defun intern-slot-class-specializer (slot-name class-name)
    (let ((class (find-class class-name)))
      (or (gethash (cons slot-name class) *slot-class-specializers*)
          (setf (gethash (cons slot-name class) *slot-class-specializers*)
                (make-instance 'slot-class-specializer 
                               :slot-name slot-name
                               :class class)))))
  and a method definition and expansion would look like:
    (define-method foo ((x foo)
                        (y (eql bar))
                        (z (slot a baz)))  ;means that the value of the
                                           ;slot named A of this argument
                                           ;should have class BAZ
       (make-instance 'my-method
         :specializers  (list (intern-class-specializer 'foo)
                              (intern-eql-specializer bar)
                              (intern-slot-class-specializer 'a 'baz))
I like this idea.  Of course, a lot of the mop now specialized on
standard-class will have to specialized on specializer, which is
probably a good thing, except for the editing.  


(defmethod foo (z (slot a bar)) ...) is a method specialized for
objects that have (eq (class-of (slot-value z 'a)) (find-class 'bar)).
(intern-specializer '(slot a bar)) returns an instance of class
How to refer to this class to specialize methods on it?

(defmethod ((s (eql (intern-specializer '(slot a bar))))) ...) ?

or do we have a specializer for specializers:

(defmethod ((s (specializer '(slot a bar)))) ...)