* lazy evaluation: Goops class/instance customization
@ 2003-05-19 11:09 Maarten Grachten
2003-05-20 17:53 ` Mikael Djurfeldt
0 siblings, 1 reply; 10+ messages in thread
From: Maarten Grachten @ 2003-05-19 11:09 UTC (permalink / raw)
Hi,
I'm trying to create a system for lazy evaluation. That is, I would like
to have a class whose slot-values are evaluated when they are accessed
(and not when the slot-values are set for the objects of that class).
I thought a way to do this would be by creating a macro
'make-lazy' that wraps a 'delay' around the initial slot-values and
customizing the class creation to put a 'force' in the
getter.
Thus, I came up with the following code:
(define-class <Lazy-Eval-Metaclass> (<class>))
(define (make-lazy-closure-variable class)
(let ((shared-variable (make-unbound)))
(list (lambda (o) (primitive-eval (force shared-variable)))
(lambda (o v) (set! shared-variable v)))))
(define-method (compute-get-n-set (c <Lazy-Eval-Metaclass>) slot-defs)
(make-lazy-closure-variable c))
(defmacro make-lazy (specification . body)
(let ((attributes (map (lambda (x)
(if (keyword? x) x (delay x)))
body)))
`(make ,specification
,@attributes)))
(define-class <lazy-class> ()
(s1 #:init-keyword #:s1 #:accessor s1)
#:metaclass <Lazy-Eval-Metaclass>)
And this works basically: when I do
(define obj (make-lazy <lazy-class> #:s1 x))
and
(define x 1)
then
(s1 obj)
returns 1.
But (perhaps not surprisingly) this approach only creates only one
slot-variable for all instances. Like the slots were all class-slots
instead of instance-slots. And I want instance slots.
Well now, in the Goops manual there is a rather abstract part about
customizing instance creation but it doesn't help me. I don't know how
to specialize the initialize method for objects, since I don't know
what basic stuff to put in the initialize methods, besides my
customized stuff. A look in goops.scm reveals:
(define-method (initialize (object <object>) initargs)
(%initialize-object object initargs))
This % stuff leaves me at a blank. So my question is either:
Can anybody tell me if there is any way to investigate the code that
was substituted by %initialize-object?
or
Does anybody see how my code above can be easily changed so as to
admit the lazy evaluation?
Thanks very much,
Maarten Grachten
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-19 11:09 lazy evaluation: Goops class/instance customization Maarten Grachten
@ 2003-05-20 17:53 ` Mikael Djurfeldt
2003-05-21 8:14 ` Maarten Grachten
0 siblings, 1 reply; 10+ messages in thread
From: Mikael Djurfeldt @ 2003-05-20 17:53 UTC (permalink / raw)
Cc: guile-user
Maarten Grachten <maarten@iiia.csic.es> writes:
> Thus, I came up with the following code:
>
> (define-class <Lazy-Eval-Metaclass> (<class>))
>
> (define (make-lazy-closure-variable class)
> (let ((shared-variable (make-unbound)))
> (list (lambda (o) (primitive-eval (force shared-variable)))
> (lambda (o v) (set! shared-variable v)))))
>
> (define-method (compute-get-n-set (c <Lazy-Eval-Metaclass>) slot-defs)
> (make-lazy-closure-variable c))
>
> (defmacro make-lazy (specification . body)
> (let ((attributes (map (lambda (x)
> (if (keyword? x) x (delay x)))
> body)))
> `(make ,specification
> ,@attributes)))
>
> (define-class <lazy-class> ()
> (s1 #:init-keyword #:s1 #:accessor s1)
> #:metaclass <Lazy-Eval-Metaclass>)
[...]
> Does anybody see how my code above can be easily changed so as to
> admit the lazy evaluation?
Please try to replace your version of compute-get-n-set with this:
(An advantage of this code is that it will work for all kinds of
slots, including instance slots and class slots.)
(define-method (compute-get-n-set (class <Lazy-Eval-Metaclass>) slot)
(let* ((g-n-s (next-method)) ;call "system" compute-get-n-set
;; now some "black magic"
(getter (if (pair? g-n-s) (car g-n-s) (standard-get g-n-s)))
(setter (if (pair? g-n-s) (cadr g-n-s) (standard-set g-n-s))))
(list (lambda (o)
(force (getter o)))
setter)))
However, `standard-get' and `standard-set' are not exported by the
standard goops module interface, so you have to use the module
(oop goops internal) instead of (oop goops).
When trying to come up with an elegant solution to your problem (which
the above isn't) I realized that we should probably extend the
metaobject prototcol to allow for what you want to do more cleanly and
conveniently. I'll put that on my TODO list.
Mikael D.
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-20 17:53 ` Mikael Djurfeldt
@ 2003-05-21 8:14 ` Maarten Grachten
2003-05-21 9:07 ` Mikael Djurfeldt
0 siblings, 1 reply; 10+ messages in thread
From: Maarten Grachten @ 2003-05-21 8:14 UTC (permalink / raw)
Cc: guile-user
On Tue, 20 May 2003, Mikael Djurfeldt wrote:
> Please try to replace your version of compute-get-n-set with this:
> (An advantage of this code is that it will work for all kinds of
> slots, including instance slots and class slots.)
>
> (define-method (compute-get-n-set (class <Lazy-Eval-Metaclass>) slot)
> (let* ((g-n-s (next-method)) ;call "system" compute-get-n-set
> ;; now some "black magic"
> (getter (if (pair? g-n-s) (car g-n-s) (standard-get g-n-s)))
> (setter (if (pair? g-n-s) (cadr g-n-s) (standard-set g-n-s))))
> (list (lambda (o)
> (force (getter o)))
> setter)))
That worked! Although to meet my wishes, I changed the getter so
that it evaluates the the slot-value if it's a promise (and checks for a
promise before doing the force):
(define-method (compute-get-n-set (class <Lazy-Eval-Metaclass>) slot)
(let* ((g-n-s (next-method)) ;call "system" compute-get-n-set
;; now some "black magic"
(getter (if (pair? g-n-s) (car g-n-s) (standard-get g-n-s)))
(setter (if (pair? g-n-s) (cadr g-n-s) (standard-set g-n-s))))
(list (lambda (o)
(let ((v (getter o)))
(if (promise? v) (primitive-eval (force v)) v)))
setter)))
Thanks, very much!
Maarten
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 8:14 ` Maarten Grachten
@ 2003-05-21 9:07 ` Mikael Djurfeldt
2003-05-21 10:46 ` Maarten Grachten
0 siblings, 1 reply; 10+ messages in thread
From: Mikael Djurfeldt @ 2003-05-21 9:07 UTC (permalink / raw)
Cc: djurfeldt
Maarten Grachten <maarten@iiia.csic.es> writes:
> That worked! Although to meet my wishes, I changed the getter so
> that it evaluates the the slot-value if it's a promise (and checks for a
> promise before doing the force):
>
> (define-method (compute-get-n-set (class <Lazy-Eval-Metaclass>) slot)
> (let* ((g-n-s (next-method)) ;call "system" compute-get-n-set
> ;; now some "black magic"
> (getter (if (pair? g-n-s) (car g-n-s) (standard-get g-n-s)))
> (setter (if (pair? g-n-s) (cadr g-n-s) (standard-set g-n-s))))
> (list (lambda (o)
> (let ((v (getter o)))
> (if (promise? v) (primitive-eval (force v)) v)))
> setter)))
Why are you using `primitive-eval'?
Shouldn't it be simply "(if (promise? v) (force v) v)"?
Best regards,
MD
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 9:07 ` Mikael Djurfeldt
@ 2003-05-21 10:46 ` Maarten Grachten
2003-05-21 14:18 ` Mikael Djurfeldt
0 siblings, 1 reply; 10+ messages in thread
From: Maarten Grachten @ 2003-05-21 10:46 UTC (permalink / raw)
Cc: guile-user
On Wed, 21 May 2003, Mikael Djurfeldt wrote:
> Why are you using `primitive-eval'?
>
> Shouldn't it be simply "(if (promise? v) (force v) v)"?
Well, without the eval the getter gives me back just the variable, and I
want the value of the variable (if there is one, and an unbound variable
error otherwise).
Maarten
--
______________________________________________________________________________
_/ _/ _/_| Maarten Grachten
/ _/ _/ _| Institut d'Investigacio en Intel.ligencia Artificial, IIIA
_/ _/___| Spanish Scientific Research Council, CSIC
_/ _/ ___| Campus UAB
/ _/ _| 08193 Bellaterra, Catalunya, Spain
Ph.: +34 93 5809570 Fax.: +34 93 5809661
maarten@iiia.csic.es
______________________________________________________________________________
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 10:46 ` Maarten Grachten
@ 2003-05-21 14:18 ` Mikael Djurfeldt
2003-05-21 14:51 ` Maarten Grachten
0 siblings, 1 reply; 10+ messages in thread
From: Mikael Djurfeldt @ 2003-05-21 14:18 UTC (permalink / raw)
Cc: djurfeldt
Maarten Grachten <maarten@iiia.csic.es> writes:
> On Wed, 21 May 2003, Mikael Djurfeldt wrote:
>
>> Why are you using `primitive-eval'?
>>
>> Shouldn't it be simply "(if (promise? v) (force v) v)"?
>
> Well, without the eval the getter gives me back just the variable, and I
> want the value of the variable (if there is one, and an unbound variable
> error otherwise).
Then, in order to get correct semantics, you should remove
`primitive-eval' and instead use the following (untested) version of
make-lazy:
(defmacro make-lazy (specification . body)
(let ((attributes (map (lambda (x)
(if (keyword? x)
x
`(delay ,x)))
body)))
`(make ,specification
,@attributes)))
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 14:18 ` Mikael Djurfeldt
@ 2003-05-21 14:51 ` Maarten Grachten
2003-05-21 16:22 ` David Allouche
2003-05-21 17:58 ` Mikael Djurfeldt
0 siblings, 2 replies; 10+ messages in thread
From: Maarten Grachten @ 2003-05-21 14:51 UTC (permalink / raw)
Cc: guile-user
On Wed, 21 May 2003, Mikael Djurfeldt wrote:
> Then, in order to get correct semantics, you should remove
> `primitive-eval' and instead use the following (untested) version of
> make-lazy:
>
> (defmacro make-lazy (specification . body)
> (let ((attributes (map (lambda (x)
> (if (keyword? x)
> x
> `(delay ,x)))
> body)))
> `(make ,specification
> ,@attributes)))
>
Ah. Indeed, that seems to work as well. But I don't really see where the
crucial difference is.
(not questioning the superiority of this solution :-)
Maarten
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 14:51 ` Maarten Grachten
@ 2003-05-21 16:22 ` David Allouche
2003-05-21 17:58 ` Mikael Djurfeldt
1 sibling, 0 replies; 10+ messages in thread
From: David Allouche @ 2003-05-21 16:22 UTC (permalink / raw)
Cc: guile-user
On Wed, May 21, 2003 at 04:51:19PM +0200, Maarten Grachten wrote:
> On Wed, 21 May 2003, Mikael Djurfeldt wrote:
>
> > Then, in order to get correct semantics, you should remove
> > `primitive-eval' and instead use the following (untested) version of
> > make-lazy:
>
[...]
>
> Ah. Indeed, that seems to work as well. But I don't really see where the
> crucial difference is.
> (not questioning the superiority of this solution :-)
Probably, some scheme guru will give a more useful answer. But I
cannot resist this:
Eval is Evil. Closures close the case.
--
-- ddaa
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 14:51 ` Maarten Grachten
2003-05-21 16:22 ` David Allouche
@ 2003-05-21 17:58 ` Mikael Djurfeldt
2003-05-22 9:25 ` Maarten Grachten
1 sibling, 1 reply; 10+ messages in thread
From: Mikael Djurfeldt @ 2003-05-21 17:58 UTC (permalink / raw)
Cc: djurfeldt
Maarten Grachten <maarten@iiia.csic.es> writes:
> On Wed, 21 May 2003, Mikael Djurfeldt wrote:
>
>> Then, in order to get correct semantics, you should remove
>> `primitive-eval' and instead use the following (untested) version of
>> make-lazy:
>>
>> (defmacro make-lazy (specification . body)
>> (let ((attributes (map (lambda (x)
>> (if (keyword? x)
>> x
>> `(delay ,x)))
>> body)))
>> `(make ,specification
>> ,@attributes)))
>>
>
> Ah. Indeed, that seems to work as well. But I don't really see where the
> crucial difference is.
> (not questioning the superiority of this solution :-)
Try the following code and compare the result for the old and the new
make-lazy:
(define c ()
(x #:init-keyword #:x #:accessor x)
#:metaclass <Lazy-Eval-Metaclass>)
(define x 1147)
(define o
(let ((x 4711))
(make-lazy c #:x x))
(x o)
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: lazy evaluation: Goops class/instance customization
2003-05-21 17:58 ` Mikael Djurfeldt
@ 2003-05-22 9:25 ` Maarten Grachten
0 siblings, 0 replies; 10+ messages in thread
From: Maarten Grachten @ 2003-05-22 9:25 UTC (permalink / raw)
Cc: guile-user
On Wed, 21 May 2003, Mikael Djurfeldt wrote:
> Maarten Grachten <maarten@iiia.csic.es> writes:
>
> > On Wed, 21 May 2003, Mikael Djurfeldt wrote:
> >
> >> Then, in order to get correct semantics, you should remove
> >> `primitive-eval' and instead use the following (untested) version of
> >> make-lazy:
> >>
> >> (defmacro make-lazy (specification . body)
> >> (let ((attributes (map (lambda (x)
> >> (if (keyword? x)
> >> x
> >> `(delay ,x)))
> >> body)))
> >> `(make ,specification
> >> ,@attributes)))
> >>
> >
> > Ah. Indeed, that seems to work as well. But I don't really see where the
> > crucial difference is.
> > (not questioning the superiority of this solution :-)
>
> Try the following code and compare the result for the old and the new
> make-lazy:
>
> (define c ()
> (x #:init-keyword #:x #:accessor x)
> #:metaclass <Lazy-Eval-Metaclass>)
>
> (define x 1147)
>
> (define o
> (let ((x 4711))
> (make-lazy c #:x x))
>
> (x o)
I see your point, when there is a bound variable at the time of using it
in make-lazy, I want to have the value of that variable, instead of the
value of the variable at the time of calling the getter. This is the
difference isn't it?
Besides, I had to change the name of the x variable, because it shadowed
the getter with the same name (such that (x o) raised a 'Wrong type to
apply: 1147'). Is this something that can be avoided?
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2003-05-22 9:25 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-19 11:09 lazy evaluation: Goops class/instance customization Maarten Grachten
2003-05-20 17:53 ` Mikael Djurfeldt
2003-05-21 8:14 ` Maarten Grachten
2003-05-21 9:07 ` Mikael Djurfeldt
2003-05-21 10:46 ` Maarten Grachten
2003-05-21 14:18 ` Mikael Djurfeldt
2003-05-21 14:51 ` Maarten Grachten
2003-05-21 16:22 ` David Allouche
2003-05-21 17:58 ` Mikael Djurfeldt
2003-05-22 9:25 ` Maarten Grachten
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).