MzScheme supports multiple namespaces for top-level
variable bindings, syntax bindings, module imports, and module
declarations.
A new namespace is created with the make-namespace procedure,
which returns a first-class namespace value. A namespace is used by
setting the current-namespace parameter value (see
section 7.4.1.5), or providing the namespace as the
second argument to eval. The MzScheme versions of the R5RS
procedures scheme-report-environment and
null-environment produce namespaces.12
The current namespace is used by eval, load,
compile, expand, and expand-once.13 After
an expression is evaled, the global variable references in the
expression are permanently attached to a particular namespace, so the
current namespace at the time that the code is executed is not
used as the namespace for referencing global variables in the
expression.
Example:
(definex'orig) ; define in the original namespace ;; The following let expression is compiled in the original ;; namespace, so direct references to x see 'orig.
(let ([n (make-namespace)]) ; make new namespace
(parameterize ([current-namespacen])
(eval'(definex'new)) ; evals in the new namespace
(displayx) ; displays 'orig
(display (eval'x)))) ; displays 'new
A namespace actually encapsulates two top-level environments: one for
normal expressions, and one for macro transformer expressions; see
section 12 for more information about the transformer
environment. Module declarations are shared by the environments, but
module instances, variable bindings, syntax bindings, and module
imports are distinct. More precisely, the transformer environment
never contains any variable or syntax bindings, and its module
instances and imports are distinct from the instances and imports of
the normal top-level environment.
Identifier resolution in the top-level environment, for compilation or
expansion, proceeds in two steps. First, the environment determines
whether the identifier is mapped to a top-level variable, to syntax,
or to a module import (which can be either syntax or a
variable). Second, if the identifier is mapped to a top-level
variable, then the variable's location is found; if the identifier is
mapped to syntax, then the expansion-time binding is found; and if
the identifier is mapped to an import, then the source module is
consulted.
Importing a variable from a module with require is not
the same as defining the variable; the import does not create a new
top-level variable in the environment, but instead maps an identifier
to the module's variable, in the same way that a syntax definition
maps an identifier to a transformer.
Redefining a previously-defined variable is the same as mutating the
variable with set!. Rebinding a syntax-bound or import-bound
identifier (to syntax or an import) replaces the old binding with the
new one for future uses of the environment.
If an identifier is bound to syntax or to an import, then defining the
identifier as a variable shadows the syntax or import in future uses
of the environment. Similarly, if an identifier is bound to a
top-level variable, then binding the identifier to syntax or an
import shadows the variable; the variable's value remains unchanged,
however, and may be accessible through previously evaluated
expressions.
In the stand-alone MzScheme application, the initial namespace
contains module declarations for mzscheme and the primitive
#%-named modules (see section 5.7). The normal
top-level environment of the initial namespace contains imports for
all MzScheme syntax, and it contains variable bindings (as opposed to
imports) for every built-in procedure and constant. The transformer
top-level environment of the initial namespace imports all MzScheme
syntax, procedures, and constants.
Applications embedding MzScheme may extend or modify the set of
initial bindings, but they will usually only add primitive modules
with #%-prefixed names. (MrEd adds #%mred-kernel
for its graphical toolbox.)
(make-namespace[flag-symbol]) creates a new namespace; the
flag-symbol is an option that determines the initial bindings
in the namespace. The allowed values for flag-symbol are:
'initial (the default) -- the new namespace
contains the module declarations of the initial namespace (see
section 8.2), and the new namespace's normal top-level
environment contains bindings and imports as in the initial
namespace. However, the namespace's transformer top-level
environment is empty.
'empty -- creates a namespace with no initial
bindings or module declarations.
(namespace?v) returns #t if v is a namespace value,
#f otherwise.
(namespace-symbol->identifiersymbol) is similar to
datum->syntax-object (see section 12.2.2) restricted to
symbols. The lexical context of the resulting identifier corresponds
to the top-level environment of the current namespace; the identifier
has no source location or properties.
(namespace-variable-valuesymbol[use-mapping? failure-thunk])
returns a value for symbol in the current namespace. The
returned value depends on use-mapping?:
If use-mapping? is true (the default), and if
symbol maps to a top-level variable or an imported variable
(see section 8.1), then the result is the same as
evaluating symbol as an expression. If symbol maps to
syntax or imported syntax, the exn:syntax exception is raised (or
failure-thunk is called; see below). If symbol is
mapped to an undefined variable or an uninitialized module
variable, the exn:variable exception is raised (or failure-thunk is
called).
If use-mapping? is false, the namespace's syntax and
import mappings are ignored. Instead, the value of the top-level
variable named symbol in namespace is returned. If the
variable is undefined, the exn:variable exception is raised (or
failure-thunk is called).
If failure-thunk is provided, namespace-variable-value
calls failure-thunk to produce the return value in place of
raising an exn:variable or exn:syntax exception.
(namespace-set-variable-value!symbol v[map?]) sets the value of
symbol in the top-level environment of the current namespace,
defining symbol if it is not already defined. If map?
is supplied as true, then the namespace's identifier mapping is also
adjusted (see section 8.1) so that symbol maps to the
variable. The default value for map? is #f.
(namespace-mapped-symbols) returns a list of all symbols that are
mapped to variables, syntax, and imports in the current namespace.
(namespace-requirequoted-require-spec) performs the import
corresponding to quoted-require-spec in the top-level
environment (like a top-level require expression). See also
Chapter 5.
(namespace-transformer-requirequoted-require-spec) performs the
import corresponding to quoted-require-spec in the top-level
transformer environment (like a top-level require-for-syntax
expression). See also Chapter 5.
(namespace-require/copyquoted-require-spec) is like
namespace-require for syntax exported from the module, but
exported variables are treated differently: the export's current
value is copied to a top-level variable in the current namespace.
(namespace-require/expansion-timequoted-require-spec) is like
namespace-require, but only the transformer part of the
module is executed. If the required module has not been invoked
before, the module's variables remain undefined.
(namespace-attach-modulesrc-namespace module-symbol) attaches
the instantiated module named module-symbol in
src-namespace to the current namespace, using
module-symbol as the module name in the current namespace. In
addition to the module-symbol module itself, every module that
it imports (directly or indirectly) is also transferred into the
current namespace. If module-symbol is not the name of an
instantiated module in src-namespace, or if the name of any
module to be transferred already has a different declaration or
instance in the current namespace, then the
exn:application:mismatch exception is raised.
12 The
resulting namespace contains syntax imports for #%app,
#%datum, and #%top, because syntax expansion
requires them (see section 12.5), but those names are not
legal R5RS identifiers.
13 More
precisely, the current namespace is used by the evaluation and load
handlers, rather than directly by eval and load.