[R6RS] modules

Richard Kelsey kelsey
Tue Aug 24 13:51:03 EDT 2004

   Date: Tue, 24 Aug 2004 11:12:14 -0500 (EST)
   From: "R. Kent Dybvig" <dyb at cs.indiana.edu>

   > ... The compiler can easily identify and indicate
   > stale requires much more accurately than a programmer.

   Perhaps, but I'd rather write my code more precisely in the first place
   and not depend on a tool,

Fair enough.

   ... and you have not addressed the other benefits
   of local requires.

I admit to having a bit of trouble keeping all the different concerns in my
head at once.

   > I wouldn't object to a local require that
   > had a body and explicitly named the identifiers being introduced.

   I prefer that the decision to explicitly name identifiers be up to
   the programmer, but I would go along with this if necessary to reach

   I assume by "having a body" you wish to rule out require as an internal
   definition form.  I don't understand why this helps with the scoping
   issue you mentioned.

Only in that bindings appear before uses.

   I've come to like internal defines in spite of my early opposition to
   them because they allow me to have mutually recursive variable, syntax,
   and derived definitions and because they lead to less indentation (call
   me superficial if you like).  It's not going to be easy to convince me
   to give them up.

I wouldn't dream of it.

The indentation benefits are the only reason I ever use internal
define's.  I have retained my initial dislike to them, but still
occasionally use them anyway.  I have concerns with extending internal
definitions to include internal syntax definitions and mixed internal
definitions and expressions, but they have nothing to do with modules
so I would prefer to keep that discussion separate.

Ideally we can keep the issue of extending internal definitions
distinct from the module discussion, which could be done by having
an internal require that had a body.  As far as I can tell there is
no semantic difference because requires have no dependence on their
own lexical environment and so can always be lifted out of the block
in which they appear.
  (let ()  ... (require a) ... (require b) ...)
is equivalent to 
  (require-with-body (a b) (let () ... ... ...))

   > If so, doesn't evaluating each module
   > only once allow contagion between compile time and run time?

   Yes.  So does the file system.

Sure, but contagion via the file system is a bit easier to detect.
It isn't likely to happen accidentally.

   I'd prefer that my system not read
   configuration files, build translation tables, etc., multiple times in
   a vain effort to prevent me from doing something "bad" that I can do in
   some other way anyway.

Preventing contagion isn't to prevent you from doing what you want to
do, but to help you avoid doing what you don't want to do.  Matthew
has reported that preventing contagion was important in detecting and
fixing problems that occured with separate compilation.  So in his
experience at least the contagion barrier was not in vain.

The question is about how many times a module gets evaluated.  I don't
see how re-evaluating a module requires reading configuration files,
building translation tables, etc.

In any case, I was making sure that I understood what you were
advocating, not arguing against it.  I am concerned with the overhead
of maintaining a full contagion barrier and am not ready to argue at
this point that it should be a requirement.  It does seem to be
to be the right thing to do, if the cost is managable.

   > I would like to drop the pathname entirely.  Failing that, it should
   > be advisory.

   Would you have a separate way to associate names with pathnames, or do
   you prefer that modules be explicitly loaded?

I am not sure that any single mechanism is going to be adequate.
Programs are executed in so many different ways.  Explicit loading
seems the most flexible, as it leaves implementations free to add
whatever implicit loading mechanism they want.

   > Not settable.  I would like to go further and prohibit any assignment
   > of exported variables, including in the exporting module.  SET! on a
   > an exported variable is rare enough that it's nice to know that it
   > can't happen at all.

   Does this include implicit exports?

No, only the explicit imports.  They are the only ones that appear in
an importing module's source code and are of interest to the someone
using the module.

   >      * Must one declare "implicit" exports, i.e., local identifiers,
   >        references to which may be contained in the expanded output of an
   >        exported macro?  (I prefer yes, since this improves security and
   >        gives the implementation a chance to treat the remaining variables
   >        more efficiently.)

   > No.  Implicit exports are the business of the implementation, not the
   > programmer.  This seems akin to requiring that the programmer list the
   > closed-over variables in a lambda.

   From an aesthetic point of view, I agree with you.  [But determining
   implicit exports is complicated and can only be done conservatively.]

Fair enough.  Do implicit re-exports of imported variables need to be
declared?  For example, if I export a macro which expands into a
reference to (Scheme's) CAR, do I need to declare it as an explicit

More information about the R6RS mailing list