[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