unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* 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).