Re: value cell for virtual slots (Re: stklos question)

From: Erick Gallesio <eg_at_kaolin.unice.fr>
Date: Fri, 16 Jan 1998 20:44:15 +0100

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