Warning 1: message sent to the PLT list, the Larceny list and the Ikarus list
Warning 2: this is long and complicated, for freaks of the module system only

I have been experimenting with side effects in modules.
>From my previous experience I expected to open a can of
worms, finding strange behaviours and inconsistencies
between implementations.  My expectations were met ;-)

I am asking for comments from the Ones Who Knows, since
I do not understand the behaviour in Larceny and PLT.

The problem I want to solve is to introduce a define+ form which
works as a regular define, but also register the
defined name via a side effect *at expand time*.

The problem is directly inspired to the "Composable
and Compilable macros" paper and I am solving it
with the sole purpose of finding the portability
issues between different implementations.

To solve the problem, I have defined three modules,
which I put in a package named "experimental".
The first module is just a registry of identifiers:

#!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)

What's the output of this script in different implementations?

Ypsilon
--------------------

At the first run Ypsilon register the definitions and prints them:

$ ypsilon x.ss
registering #<syntax a>
registering #<syntax b>
(a b)

At the second run the libraries are already compiled and I get the
empty list:

$ ypsilon x.ss
()

This is due to separate compilation and I understand what
it is going on.

Ikarus
----------------------------------------

Ikarus behaves like Ypsilon. The identifiers are registered at the first
compilation

$ ikarus --compile-dependencies x.ss
registering #<syntax a [char 94 of
/home/micheles/gcode/scheme/experimental/defines.sls]>
registering #<syntax b [char 108 of
/home/micheles/gcode/scheme/experimental/defines.sls]>
Serializing "/home/micheles/gcode/scheme/experimental/defines.sls.ikarus-fasl"
...
Serializing "/home/micheles/gcode/scheme/experimental/define+.sls.ikarus-fasl"
...

At subsequence runs I get the empty list:

$ ikarus --r6rs-script x.ss
()

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??

PLT Scheme
----------------------------------------------

PLT Scheme (I am using version 4.1.5) is even more surprising:

$ plt-r6rs x.ss
/home/micheles/.plt-scheme/4.1.5/collects/experimental/defines.sls:5:0:
compile: bad syntax; function application is not allowed, because no
#%app syntax transformer is bound in the transformer environment in:
(register (syntax a))

This message usually means that there is a phase error,
however I thought I did my homework correctly by using
the (for (experimental registry) expand) import form:
Larceny does not complain either, so there must be
something specific to PLT happening here.

I expected, had script compiled, to get consistently
the empty list, with or without separate compilation,
due to the multiple instantiation semantics of PLT.

Can you explain what it happening?

               Michele Simionato

_______________________________________________
Larceny-users mailing list
[email protected]
https://lists.ccs.neu.edu/bin/listinfo/larceny-users

Reply via email to