* 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).