Re: effective slot definitions
- From: Pascal Costanza <pc@xxxxxxxxx>
- Date: Tue, 30 Sep 2008 00:25:17 +0200
Alex Mizrahi wrote:
hi
i don't get how custom effective slot definitions
mechanism is supposed to work by MOP standard.
i was able to find only implementation-specific
examples, and implementation-agnostic version seems
to be daunting.
let's consider a simple case -- we want some fancy
slot definition with additional slot initarg. e.g.:
(defclass fancy-slot-definition (standard-slot-definition)
((fancy :initarg :fancy :accessor fancy-of)))
it's supposed to work like this, in a class definition:
(defclass fancy-object ()
((slot1 :initarg :slot1)
(slot2 :initarg :slot2 :fancy t))
(:metaclass fancy-class))
slot1 should be a standard slot definition,
and slot2 should be a fancy slot definition (slotd).
working with direct slotds is quite straightforward
-- you just specialize direct-slot-definition-class
function for your metaclass, it accepts slot initargs
as parameter, and so you can see if slot is fancy or not.
situation with effective slot definitions looks quite similar
-- you can specialize function
effective-slot-definition-class
and/or compute-effective-slot-definition.
but it only looks so. information that effective-slot-definition-class
is sort of implementation specific (it depends on implementation of
default compute-effective-slot-definition function). in SBCL it
recieves only "standard" initargs, and effectively no information
that we can use to decide if slot is fancy or not.
so we'll have to override compute-effective-slot-definition -- either re-implementing all it's machinery, or somehow re-using
default return value.
You don't need to reimplement compute-effective-slot-definition. It's actually much simpler to use than you think.
Consider:
(defvar *effective-slot-definition-class*)
(defmethod effective-slot-definition-class
((class fancy-class) &key)
*effective-slot-definition-class*)
(defmethod compute-effective-slot-definition
((class fancy-class) name direct-slots)
(let ((*effective-slot-definition-class*
(if (some #'fancy-of direct-slots)
(find-class 'fancy-effective-slot-definition)
(find-class 'standard-effective-slot-definition))))
(call-next-method)))
You could also do the following:
(defmethod effective-slot-definition-class
((class fancy-class) &key)
(find-class 'fancy-effective-slot-definition))
(defmethod compute-effective-slot-definition
((class fancy-class) name direct-slots)
(let ((effective-slot (call-next-method)))
(setf (fancy-of effective-slot)
(some #'fancy-of direct-slots))
effective-slot)))
....but I prefer not to use flags in effective slots, but rather use subclassing to indicate which features are supported or not, so that methods on slot-value-using-class etc. can be dispatched more efficiently (by specializing their slot arguments).
In order to make this approach work, fancy-of needs to work on standard slot definitions as well, but that's quite easy:
(defgeneric fancy-of (object)
(:method ((object slot-definition)) nil))
You can find more elaborate examples in the source code of ContextL (special slots, layered slots, etc.).
BTW, I agree, compute-effective-slot-definition-initargs would make life somewhat easier. But the above approach is also portable and works fine across all the major CLOS MOP implementations I am aware of.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
.
- References:
- effective slot definitions
- From: Alex Mizrahi
- effective slot definitions
- Prev by Date: Re: compiling a Lisp source to exe
- Next by Date: Re: RFC 1037 NFILE implementations around?
- Previous by thread: effective slot definitions
- Next by thread: [Ann] CLFSWM 0809 release
- Index(es):