[R6RS] `for' in `export'

Matthew Flatt mflatt at cs.utah.edu
Fri Aug 25 17:58:39 EDT 2006

At Fri, 25 Aug 2006 01:04:02 -0400, dyb at cs.indiana.edu wrote:
> The library text is not in such good shape.  There are some problems
> already with the description of phasing, some but not all of which I have
> tried to address, and we have to figure out how to account for the fact
> that both the phased and unphased models are now acceptable.
> Matthew, it would help if you could let me know how you think the library
> text needs to be modified to reflect both options and also let me know
> about any other changes you think need to be made to the text.  The
> current document source is committed in srfi/library/library.stex,
> complete with a grammar that is currently broken and several FIXMEs.


And I see that I forgot to follow-up on the issue of exports and

Currently, we have a `for' specification in `export' that supplies a
default `for' to `import'. So,

 (library (L)
   (export (for (x y z) (meta 5) (meta 88)))


 (import (L))

to mean "import x, y, and z for phases 5 and 88", whereas

 (import (for (L) (meta 17)))

means "import x, y, and z for phases 17". In the latter case, the
`(meta 5)' and `(meta 88)' of export are ignored on `import', since the
`import' has an explicit `for'.

As came up in the discussion with Andre, I would much prefer that `for'
in `export' be *composed* with `for' in `import'. In that case, the above
declaration of `(L)' causes the same meaning for 

 (import (L))

but now

 (import (for (L) (meta 17)))

means "import x, y, and z for phases 22 and 95".

There's another dimension to proposed change. In the current `for' of
`export', the named identifiers are all phase 0. I'd prefer that the
phase specified with `for' is the identifier's phase within the
exporting library. That is, the rule for exporting at phase N is the
same as referencing at phase N: the identifier must be defined at phase
N (which is possible only if N = 0) or imported at phase N.

This means the code behind "..." in the definition of `(L)' has to
change if `for' changes. With the current system, `x', `y', and `z' can
be defined as

 (library (L)
   (export (for (x y z) (meta 5) (meta 88)))
   (define x ...)
   (define y ...)
   (define z ...)

With the change I'm proposing, the programmer would have to write

 (library (L-base)
   (export x y z)
   (define x ...)
   (define y ...)
   (define z ...)

 (library (L)
   (import (for (L-base) (meta 5) (meta 88)))
   (export (for (x y z) (meta 5) (meta 88))))

I find this extra-module overhead acceptable for the rare (I believe)
cases where you want a simple `import' to pull bindings into multiple

At the same time, you get new expressiveness with the new `for'. For
example, imagine that `(r6rs)' is implemented as

 (library (r6rs)
   (export (for (cons car cdr ...) run expand))


 (library (M)
    (import (for (r6rs) (meta 43)))

works in a more natural way: a phase-43 expression can contain
`(let-syntax ([d (syntax-case ...)]) ...)' because `syntax-case' will
be imported into phase 44.

It also allows different subsets of bindings to be imported into
different phases. For example, an '(r5rs)' library might export

  (export (for (syntax-rules) expand)
          (for (cons car cdr ...) run))

to provide only `syntax-rules' in transformer expressions.

Overall, I think the change will work better in a model with phases ---
and, perhaps more importantly, will increase the likelihood that
programs implemented in a phaseless system actually work in a phased
system. Meanwhile, I don't think the changes are significant for a
phaseless system, as it only affects the way that the actual `for' of
an `import' is computed.



More information about the R6RS mailing list