Re: value cell for virtual slots (Re: stklos question)
Shiro Kawai writes:
> > From: Erick Gallesio <eg_at_kaolin.unice.fr>
> > Date: Tue, 13 Jan 1998 10:07:13 +0100
> > For instance:
> > (define setter! #f)
> > (define getter #f)
> >
> > (let ((var 0))
> > (set! getter (lambda (o) var))
> > (set! setter! (lambda (o v) (set! var v))))
> >
> > (define-class <foo> ()
> > ((slot :allocation :virtual :slot-set! setter! :slot-ref getter)))
>
> I think by this method all the instances of class <foo> shares the
> same virtual cell (closed variable "var"), so it will behave like
> :allocation :class. Also it won't work with :initform option
> (see the Erick's comment in stklos.stk).
I have changed quite a lot the STklos implementation and it works now.
I have also modified STklos such that the getter and the setter don't need
anymore to be globals. That means that you can do:
(let ((var 0))
(define getter (lambda (o) var))
(define setter! (lambda (o v) (set! var v)))
(define-class <foo> ()
((slot :allocation :virtual :slot-set! setter! :slot-ref getter))))
In this case, it's true that it behaves like a :allocation :class slot, but
of course you can imagine that the getter and setter functions are more
elaborate than that.
> When I want to have per-instance slots with custom slot-set! and
> slot-ref, usually I create a vector for each instance to hold
> "hidden" values. (Still the vector itself is not hidden.
> I don't know how to hide it completely)
>
> (define-class <foo-meta> (<class>)
> ((hidden-slot-count :initform 0)))
>
> (define-method compute-get-n-set ((class <foo-meta>) s)
> (if (eqv? (get-slot-allocation s) :hidden)
> (let* ((index (slot-ref class 'hidden-slot-count))
> ;; you can add any features to following getter and setter
> (getter (lambda (o) (vector-ref (slot-ref o 'values) index)))
> (setter (lambda (o v) (vector-set! (slot-ref o 'values) index
> v))))
> (slot-set! class 'hidden-slot-count (+ index 1))
> (list getter setter))
> (next-method)))
>
> (define-class <foo> ()
> ((values)
> (x :allocation :hidden))
> :metaclass <foo-meta>)
>
> (define-method initialize ((self <foo>) initargs)
> (slot-set! self 'values
> (make-vector (slot-ref (class-of self) 'hidden-slot-count)))
> (next-method))
>
In fact, you can hide the vector in a class slot of the class. This
slot, which is defined in the meta class <foo-meta>, is in fact a
A-list. Hereafter is a rewriting of your code using this idea.
(define-class <foo-meta> (<class>)
((hidden-slot-count :initform 0)
(all-vectors :initform '() :allocation :class)))
(define-method compute-get-n-set ((class <foo-meta>) s)
(if (eqv? (get-slot-allocation s) :hidden)
(let ((index (slot-ref class 'hidden-slot-count))
(find-vector (lambda (o)
(cdr (assoc o (slot-ref class
'all-vectors))))))
(slot-set! class 'hidden-slot-count (+ index 1))
(list (lambda (o) (vector-ref (find-vector o) index)) ; GET
(lambda (o v) (vector-set! (find-vector o) index v)))) ; SET
(next-method)))
(define-class <foo> ()
((x :allocation :hidden)
(y :allocation :hidden))
:metaclass <foo-meta>)
(define-method initialize ((self <foo>) initargs)
(let ((meta (class-of self)))
(slot-set! meta
'all-vectors
(cons (cons self
(make-vector (slot-ref meta
'hidden-slot-count)))
(slot-ref meta 'all-vectors))))
(next-method))
I have not found a better way to hide the vector, in particular I
cannot figure an easy way to hide it in an environment.
-- Erick
Received on Fri Jan 16 1998 - 22:16:16 CET
This archive was generated by hypermail 2.3.0
: Mon Jul 21 2014 - 19:38:59 CEST