schemer7rs

When is it possible to override top-level bindings in (R7RS) scheme?


I have read the current draft of the forthcoming R7RS scheme standard (small language), but I don't understand under which conditions it is not an error to redefine top-level bindings.

I guess that it is possible to define or set! a binding that has been introduced at the top-level of a program a second time. But what about imported bindings from an external library? Is it possible to override these bindings by the standard?

On page 26/27 of the report, it says:

The top level of a program may also include import declarations. In a library declaration, it is an error to import the same identifier more than once with different bindings, or to redefine or mutate an imported binding with define, define-syntax or set!. However, a REPL should permit these actions.

Does it mean that redefining is only an error when it does happen in libraries for imported bindings?

I understand that it prohibits optimisations by compilers if the compiler does not know whether, say + still means the built-in addition or is any other user-specified error. But from this perspective, it does not make sense to restrict forbidding to rebind on the library level, when it would also make sense (at least) for imported bindings in programs.

P.S.: As this is all about the environment of a scheme program: am I right in saying that environments are not first class citizens because one cannot get hold of the current environment? (Which, in turn, allows a compiled program to forget about the chosen names of the bindings.)


Solution

  • The general principle is that a binding declared in a library can only be portably mutated in that same library. If the bindings of a library are imported into a program (or into another library), they can't be mutated there. Thus, if a program imports (scheme base), the identifier + always refers to the standard addition routine (except in a region where it is locally shadowed by lambda, let, let*, or what have you, of course).

    At the REPL, or in a script being executed by a REPL, this restriction does not apply. In addition, an implementation may extend the standard language by lifting the restriction.

    The nearest equivalent to the current global environment is the result of (interaction-environment), which represents the mutable environment of the REPL if there is one. If the REPL is not in use or doesn't exist, you can simulate a current, but immutable, environment by calling environment on arguments corresponding to whatever the current set of imports may be. R7RS, like its predecessors, does not have any representation of lexical environments.