Re: how to make a "cacheing" slot

From: Erick Gallesio <Erick.Gallesio_at_unice.fr>
Date: Tue, 30 Nov 1999 14:52:40 +0100 (CET)

Brian Denheyer writes:
>
> Here's the situation :
>
> (define-class <foo> ()
> ((descriptive-value)
> (calc-value)))
>
> descriptive-value is a value which is meaningful to the user such as
> %. calc-value is a value used internally which is calculated from
> descriptive-value. It only needs to be recalculated when
> descriptive-value changes.
>
> My first thought was to make descriptive-value a virtual slot with a
> setter which will update calc-value. Since there is an actual value
> associated with descriptive-value it doesn't make sense to do this.
>

You can use an active-slot to do what you want. Active slots are
allocated but you can place a handler before/after each slot
read/write (see the file STklos/active-slot.stklos). The before
handlers can even be used as controllers. For instance, if the before
slot-set! handler return #f the slot value is not changed

To answer your problem, you can define the following class, where the
calc-value slot is always the square of the user-value slot:

    (define-class <foo> ()
      ((user-value :allocation :active
                   :accessor user-value
                   :init-keyword :user-value
                   :after-slot-set! (lambda (o v)
                                      (display "Recomputing calc-value \n")
                                      (slot-set! o 'calc-value (* v v))))
       (calc-value))
      :metaclass <Active-metaclass>)

And an example of usage:

    STk> (define o (make <foo> :user-value 10))
    Recomputing calc-value
    o
    STk> (describe o)
    #[<foo> 402173a8] is an an instance of class <foo>.
    Slots are:
         user-value = 10
         calc-value = 100
    STk> (set! (user-value o) 3)
    Recomputing calc-value
    STk> (describe o)
    #[<foo> 402173a8] is an an instance of class <foo>.
    Slots are:
         user-value = 3
         calc-value = 9

>
> P.S. For a 100pt bonus, what's a good way to do this if "cache-value"
> depends on more than 1 slot...


This scheme scales to any number of slots, the only problem is that
the after-slot-set! fuction are more difficult to write: The following
class has a slot a+b which is always the sum of the slots a and
b. Note that here we have to take into account that a slot can be
unbound when we compute the other.

    (define-class <bar> ()
      ((a :allocation :active
          :init-keyword :a
          :init-form 0
          :after-slot-set! (lambda (o v)
                             (let ((other (if (slot-bound? o 'b)
                                              (slot-ref o 'b)
                                              0)))
                               (slot-set! o 'a+b (+ v other)))))
       (b :allocation :active
          :init-keyword :b
          :init-form 0
          :after-slot-set! (lambda (o v)
                             (let ((other (if (slot-bound? o 'a)
                                              (slot-ref o 'a)
                                              0)))
                               (slot-set! o 'a+b (+ v other)))))
       (a+b))
      :metaclass <Active-metaclass>)

Hope it helps

                -- Erick
Received on Tue Nov 30 1999 - 14:55:14 CET

This archive was generated by hypermail 2.3.0 : Mon Jul 21 2014 - 19:38:59 CEST