* Simplified slot access in goops
@ 2008-11-27 20:36 Maciek Godek
2008-11-28 18:41 ` Panicz Maciej Godek
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Maciek Godek @ 2008-11-27 20:36 UTC (permalink / raw)
To: guile-user
Hi,
Below is a simple set of functions and macros to make
the access to goops object properties easier:
(use-modules (oop goops))
(use-syntax (ice-9 syncase))
(define-syntax let-alias
(syntax-rules ()
((_ ((id alias) ...) body ...)
(let-syntax ((helper (syntax-rules ()
((_ id ...) (begin body ...)))))
(helper alias ...)))))
(define slot (make-procedure-with-setter slot-ref slot-set!))
(define-syntax in (syntax-rules ()
((_ object expr ...)
(primitive-eval
(list 'let-alias
(map (lambda(s)(list(car s)(list 'slot object (list 'quote (car s)))))
(class-slots (class-of object)))
(quote expr) ...)))))
Now suppose we have an instance of a class:
(define-class C ()
a b c)
(define o (make C))
Using the "in" macro, we can write:
(in o
(set! a 5)
(set! b (1+ a))
(set! c (+ a b))
(+ a b c))
=> 22
which is more convenient than:
(slot-set! o 'a 5)
(slot-set! o 'b (1+ (slot-ref o 'a))
(slot-set! o 'c (+ (slot-ref o 'a) (slot-ref o 'b)))
(+ (slot-ref o 'a) (slot-ref o 'b) (slot-ref o 'c))
Perhaps the possible inconvenience is that all variable
names that happen to be the slot names of a given class
are shadowed. In the long run it may also cause significant
performance problems (or that's what I think), especially
when dealing with objects with a hell lotta slots.
I wonder if it would be possible to make it optimizable
for the JIT compiler somehow (and to make the "in" syntax
official part of GOOPS)
Sincerely,
M.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2008-11-27 20:36 Simplified slot access in goops Maciek Godek
@ 2008-11-28 18:41 ` Panicz Maciej Godek
2008-12-01 22:25 ` Neil Jerram
2010-08-28 20:07 ` Andy Wingo
2 siblings, 0 replies; 9+ messages in thread
From: Panicz Maciej Godek @ 2008-11-28 18:41 UTC (permalink / raw)
To: Maciek Godek; +Cc: guile-user
Unfortunately, the "in" macro fails to work with local bindings,
so the code:
(let ((z 0))
(in o
(set! a z)))
woudn't work, because primitive-eval doesn't catch the
environment from the current context.
I've tried to replace it with (eval ... (interaction-environment)),
but it still fails. Also (local-eval ... (the-environment) didn't
seem to work.
If anyone has any idea how to cope with that, please help.
Or perhaps there is a better way to handle these slot references?
Any ideas?
Regards
M.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2008-11-27 20:36 Simplified slot access in goops Maciek Godek
2008-11-28 18:41 ` Panicz Maciej Godek
@ 2008-12-01 22:25 ` Neil Jerram
2008-12-02 9:32 ` Clinton Ebadi
2010-08-28 20:07 ` Andy Wingo
2 siblings, 1 reply; 9+ messages in thread
From: Neil Jerram @ 2008-12-01 22:25 UTC (permalink / raw)
To: Maciek Godek; +Cc: guile-user
2008/11/27 Maciek Godek <pstrychuj@gmail.com>:
> Perhaps the possible inconvenience is that all variable
> names that happen to be the slot names of a given class
> are shadowed. In the long run it may also cause significant
> performance problems (or that's what I think), especially
> when dealing with objects with a hell lotta slots.
>
> I wonder if it would be possible to make it optimizable
> for the JIT compiler somehow (and to make the "in" syntax
> official part of GOOPS)
I think this is a nice interface; but I'm less sure about the
implementation. Why do you need to use primitive-eval at all?
Isn't CL's with-slots a bit like this? It might help to look at how
that is implemented.
Neil
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2008-12-01 22:25 ` Neil Jerram
@ 2008-12-02 9:32 ` Clinton Ebadi
2008-12-02 19:30 ` Panicz Maciej Godek
0 siblings, 1 reply; 9+ messages in thread
From: Clinton Ebadi @ 2008-12-02 9:32 UTC (permalink / raw)
To: Neil Jerram; +Cc: guile-user
"Neil Jerram" <neiljerram@googlemail.com> writes:
> 2008/11/27 Maciek Godek <pstrychuj@gmail.com>:
>
>> Perhaps the possible inconvenience is that all variable
>> names that happen to be the slot names of a given class
>> are shadowed. In the long run it may also cause significant
>> performance problems (or that's what I think), especially
>> when dealing with objects with a hell lotta slots.
>>
>> I wonder if it would be possible to make it optimizable
>> for the JIT compiler somehow (and to make the "in" syntax
>> official part of GOOPS)
>
> I think this is a nice interface; but I'm less sure about the
> implementation. Why do you need to use primitive-eval at all?
>
> Isn't CL's with-slots a bit like this? It might help to look at how
> that is implemented.
with-slots uses symbol-macrolet[0] to bind each of the variable names to
symbol macros within its body. I don't know of anything in Guile that is
equivalent.
[0] http://franz.com/support/documentation/6.0/ansicl/dictentr/symbol-m.htm
--
Ruled by the ebb of my oceans
Slaves to the dusk and the dawn
Your petri dish civilisations
Are buried and born
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2008-12-02 9:32 ` Clinton Ebadi
@ 2008-12-02 19:30 ` Panicz Maciej Godek
2008-12-02 20:33 ` Clinton Ebadi
0 siblings, 1 reply; 9+ messages in thread
From: Panicz Maciej Godek @ 2008-12-02 19:30 UTC (permalink / raw)
To: Clinton Ebadi; +Cc: guile-user, Neil Jerram
Neil wtote:
>> I think this is a nice interface; but I'm less sure about the
>> implementation. Why do you need to use primitive-eval at all?
>>
>> Isn't CL's with-slots a bit like this? It might help to look at how
>> that is implemented.
Well, I've been having similar doubts, so I came up with something
which turned out to be similar to CLOS's with-slots. The previous solution
indeed required primitive-eval (or something similar), because it
wasn't just a syntax transformation -- that is, it invoked the class-slots
and class-of functions
The workaround requires the user to enumerate all the slots that
he or she is going to access. I wrote two macros, so you can write
(continuing the example from the previous letter):
(with-object-slots (o a b c)
(set! a 5)
(set! b (* a a))
(set! c (+ a b))
(list a b c))
=> (2 25 30)
you don't have to use the original slot names;
you can also use the `with-object-slots' macro supplying aliases:
(with-object-slots (o (x a) (y b) (z c))
(set! x (+ y z))
(list x y z))
=> (55 25 30)
the only problem is that you can't mix both ways, ie.
! (with-object-slots (o a (y b)) (+ a y))
would be incorrect (it is possible to implement such a macro,
but for now this one should suffice). It's still ok to write
(with-object-slots (o (a a) (y b)) (+ a y))
=> 80
The second macro, let-slots allows to make aliases for slots of more
than one object, for instance:
(define p (make C))
(let-slots ((o a b c)
(p (pa a) (pb b) (pc c)))
(set! a 5)
(set! pa a)
(+ pa a))
Everything should work just fine.
The implementation is based solely on R5RS macro system and the
make-procedure-with-setter, that is afaik specific to guile
Clinton wrote:
> with-slots uses symbol-macrolet[0] to bind each of the variable names to
> symbol macros within its body. I don't know of anything in Guile that is
> equivalent.
R5RS pattern language allows to create syntactic aliases for practically
any form. Some time ago I've found the following `let-alias' macro that does
just this:
(use-syntax (ice-9 syncase))
(define-syntax let-alias
(syntax-rules ()
((_ ((id alias) ...) body ...)
(let-syntax ((helper (syntax-rules ()
((_ id ...) (begin body ...)))))
(helper alias ...)))))
;; And here's the code for the aforementioned with-object-slots and let-slots:
(use-modules (oop goops))
(define slot-ref (make-procedure-with-setter slot-ref slot-set!))
(define-syntax with-object-slots (syntax-rules ()
((_ (object (alias1 slot1) ...) expr1 ...)
(let-alias ((alias1 (slot-ref
object (quote slot1))) ...)
expr1 ...))
((_ (object prop1 ...) expr1 ...)
(let-alias ((prop1 (slot-ref object
(quote prop1))) ...)
expr1 ...))))
(define-syntax let-slots (syntax-rules ()
((_ () expr1 ...)
(begin expr1 ...))
((_ (binding1 binding2 ...) expr1 ...)
(with-object-slots binding1
(let-slots (binding2 ...)
expr1 ...)))))
It is also possible to define the `with-slots' macro exactly
as it is in CLOS (but I think let-slots is fine)
Cheers
M.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2008-12-02 19:30 ` Panicz Maciej Godek
@ 2008-12-02 20:33 ` Clinton Ebadi
0 siblings, 0 replies; 9+ messages in thread
From: Clinton Ebadi @ 2008-12-02 20:33 UTC (permalink / raw)
To: Panicz Maciej Godek; +Cc: guile-user, Neil Jerram
"Panicz Maciej Godek" <godek.maciek@gmail.com> writes:
>> with-slots uses symbol-macrolet[0] to bind each of the variable names to
>> symbol macros within its body. I don't know of anything in Guile that is
>> equivalent.
>
> R5RS pattern language allows to create syntactic aliases for practically
> any form. Some time ago I've found the following `let-alias' macro that does
> just this:
Ah, I suspected that syntax-case supported something like this.
> (use-syntax (ice-9 syncase))
>
> (define-syntax let-alias
> (syntax-rules ()
> ((_ ((id alias) ...) body ...)
> (let-syntax ((helper (syntax-rules ()
> ((_ id ...) (begin body ...)))))
> (helper alias ...)))))
>
> ;; And here's the code for the aforementioned with-object-slots and let-slots:
>
> (use-modules (oop goops))
> (define slot-ref (make-procedure-with-setter slot-ref slot-set!))
>
> (define-syntax with-object-slots (syntax-rules ()
> ((_ (object (alias1 slot1) ...) expr1 ...)
> (let-alias ((alias1 (slot-ref
> object (quote slot1))) ...)
> expr1 ...))
> ((_ (object prop1 ...) expr1 ...)
> (let-alias ((prop1 (slot-ref object
> (quote prop1))) ...)
> expr1 ...))))
>
> (define-syntax let-slots (syntax-rules ()
> ((_ () expr1 ...)
> (begin expr1 ...))
> ((_ (binding1 binding2 ...) expr1 ...)
> (with-object-slots binding1
> (let-slots (binding2 ...)
> expr1 ...)))))
--
Ethan: i'm working on myself
Ethan: the self is the most important thing
Ethan: i learned this from a packet of tea
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2008-11-27 20:36 Simplified slot access in goops Maciek Godek
2008-11-28 18:41 ` Panicz Maciej Godek
2008-12-01 22:25 ` Neil Jerram
@ 2010-08-28 20:07 ` Andy Wingo
2010-08-29 0:22 ` Panicz Maciej Godek
2 siblings, 1 reply; 9+ messages in thread
From: Andy Wingo @ 2010-08-28 20:07 UTC (permalink / raw)
To: Maciek Godek; +Cc: guile-user
Hi Maciek,
I know its been a couple years, but you raised an interesting point that
Guile wasn't really able to handle at that point. Your implementation of
`in' (commonly known as `with-slots', I believe) follows the mail.
On Thu 27 Nov 2008 12:36, "Maciek Godek" <pstrychuj@gmail.com> writes:
> (use-modules (oop goops))
> (use-syntax (ice-9 syncase))
With Guile 2.0 (coming shortly!), there is no more need to use ice-9
syncase.
> Now suppose we have an instance of a class:
> (define-class C ()
> a b c)
> (define o (make C))
>
> Using the "in" macro, we can write:
> (in o
> (set! a 5)
> (set! b (1+ a))
> (set! c (+ a b))
> (+ a b c))
> => 22
The problem with this macro is that `o' can be of any type at all, but
Guile needs to know at least whether a given identifier is a macro or a
local variable or what, at expansion time.
So for that reason, with-slots usually takes a list of slots, explicitly:
(with-slots o (a b c)
(set! a 5)
(set! b (1+ a))
(set! c (+ a b))
(+ a b c))
It would be possible to pass the class instead, but then the class would
need to be known at compile-time, and you run into a number of issues
there. Anyway, here's that with-slots definition:
(define-syntax with-slots
(syntax-rules ()
((_ obj (slot ...) b b* ...)
(let-syntax
((slot (identifier-syntax
(id (slot-ref obj 'slot))
((set! id val) (slot-set! obj 'slot val))))
...)
b b* ...))))
Here we use the new settable identifier-syntax.
Note that slot-ref / slot-set isn't the most efficient way to reference
slots; the best thing is to use accessors, which JIT-compile (sorta) to
struct-ref opcodes, but we don't know that accessors exist for these
slots. You can define a with-accessors macro though, that does assume
accessors are available.
In fact with more assumptions, it's possible to compile to struct-ref /
struct-set yourself -- see the examples in the "Syntax" chapter of "The
Scheme Programming Language" 4th edition (available online) for an
illuminating take on the issue.
Cheers,
Andy
The original definition:
> (define-syntax let-alias
> (syntax-rules ()
> ((_ ((id alias) ...) body ...)
> (let-syntax ((helper (syntax-rules ()
> ((_ id ...) (begin body ...)))))
> (helper alias ...)))))
>
> (define slot (make-procedure-with-setter slot-ref slot-set!))
>
> (define-syntax in (syntax-rules ()
> ((_ object expr ...)
> (primitive-eval
> (list 'let-alias
> (map (lambda(s)(list(car s)(list 'slot object (list 'quote (car s)))))
> (class-slots (class-of object)))
> (quote expr) ...)))))
>
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2010-08-28 20:07 ` Andy Wingo
@ 2010-08-29 0:22 ` Panicz Maciej Godek
2010-08-29 0:56 ` Andy Wingo
0 siblings, 1 reply; 9+ messages in thread
From: Panicz Maciej Godek @ 2010-08-29 0:22 UTC (permalink / raw)
To: Andy Wingo; +Cc: guile-user, Maciek Godek
2010/8/28 Andy Wingo <wingo@pobox.com>:
> Hi Maciek,
>
> I know its been a couple years, but you raised an interesting point that
> Guile wasn't really able to handle at that point. Your implementation of
> `in' (commonly known as `with-slots', I believe) follows the mail.
>
> On Thu 27 Nov 2008 12:36, "Maciek Godek" <pstrychuj@gmail.com> writes:
>
>> (use-modules (oop goops))
>> (use-syntax (ice-9 syncase))
>
> With Guile 2.0 (coming shortly!), there is no more need to use ice-9
> syncase.
>
>> Now suppose we have an instance of a class:
>> (define-class C ()
>> a b c)
>> (define o (make C))
>>
>> Using the "in" macro, we can write:
>> (in o
>> (set! a 5)
>> (set! b (1+ a))
>> (set! c (+ a b))
>> (+ a b c))
>> => 22
>
> The problem with this macro is that `o' can be of any type at all, but
> Guile needs to know at least whether a given identifier is a macro or a
> local variable or what, at expansion time.
>
> So for that reason, with-slots usually takes a list of slots, explicitly:
>
> (with-slots o (a b c)
> (set! a 5)
> (set! b (1+ a))
> (set! c (+ a b))
> (+ a b c))
>
> It would be possible to pass the class instead, but then the class would
> need to be known at compile-time, and you run into a number of issues
> there. Anyway, here's that with-slots definition:
>
> (define-syntax with-slots
> (syntax-rules ()
> ((_ obj (slot ...) b b* ...)
> (let-syntax
> ((slot (identifier-syntax
> (id (slot-ref obj 'slot))
> ((set! id val) (slot-set! obj 'slot val))))
> ...)
> b b* ...))))
>
> Here we use the new settable identifier-syntax.
>
> Note that slot-ref / slot-set isn't the most efficient way to reference
> slots; the best thing is to use accessors, which JIT-compile (sorta) to
> struct-ref opcodes, but we don't know that accessors exist for these
> slots. You can define a with-accessors macro though, that does assume
> accessors are available.
>
> In fact with more assumptions, it's possible to compile to struct-ref /
> struct-set yourself -- see the examples in the "Syntax" chapter of "The
> Scheme Programming Language" 4th edition (available online) for an
> illuminating take on the issue.
It's good to know all that. Indeed, it's been some time and the
development of my project has lost some of its robustness,
but maybe I would continue my work soon, so this news can
turn out to be motivating :)
If it comes to the performance issues, I've been wondering,
what is the current state of guile-vm? I have a friend who's been
developing a variant of a SECD machine in order to research
the topics of partial evaluation. You can take a look at his project
here:
http://drczlang.sourceforge.net/
If you think that it would make sense, I could try to convince him
to contribute to guile-vm. (I have no idea how this machine is
implemented, but I've been thinking about implementing a SECD
atop of i386 assembler; I'm only not sure whether gcc isn't wiser
than me when it comes to low-level programming)
best regards
m
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Simplified slot access in goops
2010-08-29 0:22 ` Panicz Maciej Godek
@ 2010-08-29 0:56 ` Andy Wingo
0 siblings, 0 replies; 9+ messages in thread
From: Andy Wingo @ 2010-08-29 0:56 UTC (permalink / raw)
To: Panicz Maciej Godek; +Cc: guile-user, Maciek Godek
On Sat 28 Aug 2010 17:22, Panicz Maciej Godek <godek.maciek@gmail.com> writes:
> If it comes to the performance issues, I've been wondering,
> what is the current state of guile-vm?
Merged into Guile :-)
Cheers,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-08-29 0:56 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-27 20:36 Simplified slot access in goops Maciek Godek
2008-11-28 18:41 ` Panicz Maciej Godek
2008-12-01 22:25 ` Neil Jerram
2008-12-02 9:32 ` Clinton Ebadi
2008-12-02 19:30 ` Panicz Maciej Godek
2008-12-02 20:33 ` Clinton Ebadi
2010-08-28 20:07 ` Andy Wingo
2010-08-29 0:22 ` Panicz Maciej Godek
2010-08-29 0:56 ` Andy Wingo
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).