[Larceny-users] side effects in R6RS modules
Andre van Tonder
andre at het.brown.edu
Sun May 3 12:30:31 EDT 2009
On Sun, 3 May 2009, Michele Simionato wrote:
> #!r6rs
> (library (experimental registry)
> (export registry register)
> (import (rnrs))
>
> (define _registry '())
>
> (define (registry)
> _registry)
>
> (define (register id)
> (display "registering ")
> (display id)
> (newline)
> (set! _registry (append _registry (list id)))
> _registry)
> )
>
> The second module exports the define+ form, as well
> as a define-registered form to save the list of
> registered names into a runtime variable:
>
> #!r6rs
> (library (experimental define+)
> (export define-registered define+)
> (import (rnrs) (for (experimental registry) expand))
>
> ;; save the content of the expand-time registry into a runtime definition
> (define-syntax define-registered
> (lambda (x)
> (syntax-case x ()
> ((define-registered names)
> #`(define names '#,(registry))))))
>
> (define-syntax define+
> (lambda (x)
> (syntax-case x ()
> ((define+ name value)
> #'(begin
> ;; dirty trick to get an expand time side effect
> (define-syntax dummy (begin (register #'name) (lambda (x) #f)))
> ;; the real definition
> (define name value))))))
> )
>
> The third module contains just a couple of definitions:
>
> #!r6rs
> (library (experimental defines)
> (export a b)
> (import (experimental define+))
> (define+ a 1)
> (define+ b 2)
> )
>
> I have also defined a script importing the definitions:
>
> $ cat x.ss
> #!r6rs
> (import (rnrs) (experimental define+) (experimental defines))
> (define-registered names)
> (display names)
>
> Larceny
> -----------------------------------------------------
>
> The behavior of Larceny surprises me:
>
> $ larceny-r6rs x.ss
> registering #<record identifier>
> registering #<record identifier>
> registering #<record identifier>
> registering #<record identifier>
> (a b a b)
>
> Why are the identifiers registered twice??
I can only speak for Larceny. I believe this behaviour is allowded by R6RS and
occurs as follows: During expansion of (experimental defines), its syntax
definitions have to be evaluated and so the identifiers are registered the
first time. I think that this must happen is obvious. Then, during
/expansion/ of the script x.ss, the library (experimental defines) is
/visited/, in other words, its syntax definitions are evaluated, and this will
cause the identifiers to be registered a second time - in general this must
happen for syntax definitions that are used in the script. In the present case,
none of its syntax definitions are used, so this does not /have/ to happen but
it happens anyway for consistency. As
far as I understand, Ikarus will only /visit/ imported
libraries whose syntax definitions are in fact used in the importing
library, which is also allowed by R6RS and would explain its different
behaviour.
In this case, Larceny basically adopted this aspect of its behaviour from the
"compilable and composable macros" paper (by the athor of the PLT is model)
and I believe the example in that paper will also help explain why things are
registered twice in your example.
As far as I understand, PLT /used to/ work similar to Larceny for your example.
In other words, identifiers should be registered twice in PLT also in its model
that used to be based on the same paper. I
don't know if there is some other error. If you can get PLT to work, though, I
would bet that the final printout that you get is (a b) and not (a b a b). If
you can get to that stage, I would be happy to explain why that happens.
Andre
More information about the Larceny-users
mailing list