This section describes the semantics of Gauche modules and its API. See also Writing Gauche modules, for the conventions Gauche is using for its modules.
For R7RS programs, they are called “libraries” and have different syntax than Gauche modules. See R7RS library form, for the details.
|• Module semantics:|
|• Modules and libraries:|
|• Defining and selecting modules:|
|• Using modules:|
|• Module inheritance:|
|• Module introspection:|
|• Predefined modules:|
Module is an object that maps symbols onto bindings, and affects the resolution of global variable reference.
Unlike CommonLisp’s packages, which map names to symbols,
in Gauche symbols are
eq? in principle if two have the
same name (except uninterned symbols; see Symbols).
However, Gauche’s symbol doesn’t have a ’value’
slot in it. From a given symbol, a module finds its binding that
keeps a value.
Different modules can associate different bindings
to the same symbol, that yield different values.
;; Makes two modules A and B, and defines a global variable 'x' in them (define-module A (define x 3)) (define-module B (define x 4)) ;; #<symbol 'x'> ---[module A]--> #<binding that has 3> (with-module A x) ⇒ 3 ;; #<symbol 'x'> ---[module B]--> #<binding that has 4> (with-module B x) ⇒ 4
A module can export a part or all of its bindings for other module to use. A module can import other modules, and their exported bindings become visible to the module. A module can import any number of modules.
(define-module A (export pi) (define pi 3.1416)) (define-module B (export e) (define e 2.71828)) (define-module C (import A B)) (select-module C) (* pi e) ⇒ 8.539748448
A module can also be inherited, that is, you can extend
the existing module by inheriting it and adding new bindings
and exports. From the new module, all ancestor’s bindings (including
non-exported bindings) are visible.
(A new module inherits the
gauche module by default, which is why
the built-in procedures and syntax of
gauche are available
in the new module).
From outside, the new module looks like having
all exported bindings of the original module plus the newly
defined and exported bindings.
;; Module A defines and exports deg->rad. ;; A binding of pi is not exported. (define-module A (export deg->rad) (define pi 3.1416) ;; not exported (define (deg->rad deg) (* deg (/ pi 180)))) ;; Module Aprime defines and exports rad->deg. ;; The binding of pi is visible from inside Aprime. (define-module Aprime (extend A) (export rad->deg) (define (rad->deg rad) (* rad (/ 180 pi)))) ;; Module C imports Aprime. (define-module C (import Aprime) ;; Here, both deg->rad and rad->deg are visible, ;; but pi is not visible. )
At any moment of the compilation, there is one "current module" available, and the global variable reference is looked for from the module. If there is a visible binding of the variable, the variable reference is compiled to the access of the binding. If the compiler can’t find a visible binding, it marks the variable reference with the current module, and delays the resolution of binding at the time the variable is actually used. That is, when the variable is referenced at run time, the binding is again looked for from the marked module (not the current module at the run time) and if found, the variable reference code is replaced for the the code to access the binding. If the variable reference is not found even at run time, an ’undefined variable’ error is signaled.
Once the appropriate binding is found for the global variable, the access to the binding is hard-wired in the compiled code and the global variable resolution will never take place again.
The definition special form such as
inserts the binding to the current module. Thus it may shadow
the binding of imported or inherited modules.
The resolution of binding of a global variable happens like this. First, the current module is searched. Then, each imported module is taken in the reverse order of import, and searched, including each module’s ancestors. Note that import is not transitive; imported module list is not chased recursively. Finally, ancestors of the current module are searched in order.
This order is important when more than one modules
defines the same name and your module imports both.
Assuming your module don’t define that name,
if you first import a module
A then a module
If you import
the last import takes precedence; that is, you’ll see
If two modules you want to use exports bindings of the same name and you want to access both, you can add prefix to either one (or both). See Using modules, for the details.
Modules are run-time data structure; you can procedurally create modules with arbitrary names at run-time.
However, most libraries use modules to create their own namespace, so that they can control which bindings to be visible from library users. (This “library” is a general term, broader than R7RS “library”).
Usually a library is provided in the form of one or more Scheme
source file(s), so it is convenient to have a convention to map
module names to file names, and vice versa; then, you can load a
library file and import its module by one action with
macro, for example.
For the time being, Gauche uses a simple rules for this mapping:
Module names are organized hierarchically, using period ‘
for separator, e.g.
gauche.mop.validator. If such a
module is requested and doesn’t exist in the current running
environment, Gauche maps the module name to a pathname by
replacing periods to directory separator, i.e.
gauche/mop/validator, and look for
gauche/mop/validator.scm in the load paths.
Note that this is just a default behavior.
Theoretically, one Scheme source file may contain multiple
modules, or one module implementation may span to multiple files.
In future, there may be some hook to customize this mapping
for special cases. So, when you are writing routines that
deal with modules and library files, do not apply the above
default rule blindly. Gauche provides two procedures,
to do mapping for you (see Module introspection, for details).
Name must be a symbol. If a module named name does not exist, create one. Then evaluates body sequentially in the module.
Makes a module named name as the current module. It is an error if no module named name exists.
select-module is used in the Scheme file, its effect is
limited inside the file, i.e. even if you load/require a file that uses
select-module internally, the current module of requirer is
Evaluates body sequentially in the module named name. Returns the last result(s). If no module named name, an error is signaled.
Evaluates to the current module in the compile context. Note that this is a special form, not a function. Module in Gauche is statically determined at compile time.
(define-module foo (export get-current-module) (define (get-current-module) (module-name (current-module)))) (define-module bar (import foo) (get-current-module)) ⇒ foo ; not bar
[R7RS base] Makes bindings specified by each spec available to modules that imports the current module.
Each spec can be either one of the following forms, where name and exported-name are symbols.
The binding with name is exported.
(rename name exported-name)
The binding with name is exported under an alias exported-name.
Note: In Gauche,
export is just a special form
you can put in the middle of the program, whereas
export as a library declaration,
that can only appear immediately below
See R7RS library form, for the details.
Makes all bindings in the current module available to modules that imports it.
Makes all or some exported bindings in the module specified by import-spec available in the current module. The syntax of import-spec is as follows.
<import-spec> : <module-name> | (<module-name> <import-option> ...) <import-option> : :only (<symbol> ...) | :except (<symbol> ...) | :rename ((<symbol> <symbol>) ...) | :prefix <symbol> <module-name> : <symbol>
The module named by module-name should exist when the compiler sees this special form.
Imports are not transitive. The modules that module-names are importing are not automatically imported to the current module. This keeps modules’ modularity; a library module can import whatever modules it needs without worrying about polluting the namespace of the user of the module.
import-option can be used to change how the bindings
are imported. With
:only, only the bindings with
the names listed in
<symbol> … are imported.
:except, the exported bindings except the ones
with the listed names are imported.
:rename, the binding of each name in the first
of two-symbol list is renamed to the second of it.
:prefix, the exported bindings are visible with
the names that are prefixed by the symbol to the original names.
Without import options, all the exported bindings are imported
without a prefix.
(define-module M (export x y) (define x 1) (define y 2) (define z 3)) (import M) x ⇒ 1 z ⇒ error. z is not exported from M (import (M :only (y))) x ⇒ error. x is not in :only list. (import (M :except (y))) y ⇒ error. y is excluded by :except. (import (M :prefix M:)) x ⇒ error M:x ⇒ 1 M:y ⇒ 2
If more than one import option are given, it is processed
as the order of appearance. That is, if
comes first, then
:except has to
list the name with prefix.
Note: R7RS has
import form, which has slightly different
syntax and semantics. See Three forms of import, for the details.
A convenience macro that combines module imports and on-demand
file loading. Basically,
(use foo) is equivalent
to the following two forms:
(require "foo") (import foo)
That is, it loads the library file named “
foo” (if not yet
loaded) which defines a module named
foo in it,
and then import the module
foo into the current module.
The keyword argument only, except, and prefix
are passed to
import as the import options.
(use srfi-1 :only (iota) :prefix srfi-1:) (srfi-1:iota 3) ⇒ (0 1 2)
Although the files and modules are orthogonal concept,
it is practically convenient to separate files by modules.
Gauche doesn’t force you to do so, and you can always use
import separately. However, all
modules provided with Gauche are arranged so that they can be
If a module is too big to fit in one file, you can split them into several subfiles and one main file. The main file defines the module, and either loads, requires, or autoloads subfiles.
Actually, the file pathname of the given module name is
obtained by the procedure
The default rule is to replace periods ‘
.’ in the name
/’; for example,
(use foo.bar.baz) is expanded to:
(require "foo/bar/baz") (import foo.bar.baz)
This is not very Scheme-ish way, but nevertheless convenient. In future, there may be some mechanism to customize this mapping.
The file to be
use’d must have explicit module selection
to have any toplevel definitions
define-library). If you get an error saying
“Attempted to create a binding in a sealed module:
module: #<module gauche.require-base>”, that’s because the file
lacks module selection. See Require and provide, for further
The export-import mechanism doesn’t work well in some cases, such as:
You can use module inheritance in these cases.
Makes the current module inherit from named modules. The current inheritance information is altered by the inheritance information calculated from given modules.
A new module inherits from
gauche module when created.
If you put
(extend scheme) in that module, for example,
the module resets to inherit directly from
that has only bindings defined in R5RS, hence, after the export
form, you can’t use ’import’ or any other
bindings in the module.
If a named module is not defined yet,
tries to load it, using the same convention
use macro does.
A module can inherit multiple modules, exactly the same way as a class can inherit from multiple classes. The resolution of order of inheritance needs to be explained a bit.
Each module has a module precedence list, which lists
modules in the order of how they are searched. When the module
inherits multiple modules, module precedence lists of inherited
modules are merged into a single list, keeping the constraints
that: (1) if a module A appears before module B in some module
precedence list, A has to appear before B in the resulting module
precedence list; and (2) if a module A appears before module B
extend form, A has to appear before B in the resulting
module precedence list. If no precedence list can be constructed
with these constraints, an error is signaled.
For example, suppose you wrote a library in modules
You can bundle those modules into one module by creating
mylib, as follows:
(define-module mylib (extend mylib.system mylib.util mylib.base))
The user of your module just says
(use mylib) and
all exported symbols from three submodules become available.
This subsection lists procedures that operates on modules at run-time. With these procedures you can introspect the modules, create new modules procedurally, or check the existence of certain modules/libraries, for example. However, don’t forget that modules are primarily compile-time structures. Tweaking modules at run-time is only for those who know what they are doing.
A module class.
Returns true if obj is a module.
Returns a module object whose name is a symbol name.
If the named module doesn’t exist,
#f is returned.
Creates and returns a module that has symbol name.
If the named module already exists, the behavior is specified by
if-exists keyword argument. If it is
an error is signaled. If it is
#f is returned.
Note that creating modules on-the-fly isn’t usually necessary
for ordinal scripts, since to execute already written program requires modules
to be specified by name, i.e. syntax
with-module all take module names, not
It is because module are inherently compile-time structures.
However, there are some cases that dynamically created modules
are useful, especially the program itself is dynamically created.
You can pass a module to
eval to compile and
evaluate such dynamically created
programs in it (see Eval and repl).
You can also pass
#f to name to create
anonymous module. Anonymous modules can’t be
looked up by
find-module, nor can be imported
or inherited (since
module names, not modules).
It is useful when you want to have a temporary, segregated namespace
dynamically—for example, you can create an anonymous module
to evaluate code fragments sent from other program, and
discards the module when the connection is terminated.
Anonymous modules are not registered in the system dictionary
and are garbage collected when nobody keeps reference to it.
R7RS provides another way to create a transient module
environment procedure. see R7RS eval for the
Returns a list of all named modules. Anonymous modules are not included.
Accessors of a module object. Returns the name of the module (a symbol), list of imported modules, list of exported symbols, and a hash table that maps symbols to bindings, of the module are returned, respectively.
It is an error to pass a non-module object.
Returns the information of module inheritance.
Module-parents returns the modules module directly inherits
Module-precedence-list returns the module precedence
list of module (see Module inheritance).
Returns true if symbol’s global binding is visible from module. Module must be a module object or a symbol name of an existing module.
Note: there used to be the
symbol-bound? procedure to
check whether a global variable is bound. It is deprecated and
the new code should use
The reason of change is that because of the name
the fact that it assumes current-module by default, it gives
an illusion as if a global bound value is somewhat ’stored’
in a symbol itself (like CommonLisp’s model). It caused a lot
of confusion when the current module differs between
compile-time and runtime. The new name and API made it clear
that you are querying module’s property.
Returns a value globally bound to the symbol visible from module. Module must be a module object or a symbol name of an existing module. If there’s no visible global binding from module for symbol, an error is signaled, unless the default argument is provided, in which case it is returned instead.
Converts a module name symbol to a fragment of pathname string
(which you use for
Reverse function of
If you want to find out specific libraries and/or modules are installed in the system and available from the program, see Operations on libraries.
Several modules are predefined in Gauche.
This module corresponds to the null environment referred in R5RS. This module contains only syntactic bindings of R5RS syntax.
This module contains all the binding of
and the binding of procedures defined in R5RS.
Note that if you change the current module to
select-module, there will be no way
to switch back to other modules, since module-related syntaxes
and procedures are not visible from
This module contains all the bindings of
plus Gauche specific built-in procedures.
This module is the default module the user code is compiled.
all the bindings of
gauche module is imported.
When Gauche is running with
GAUCHE_KEYWORD_IS_SYMBOL mode (default)
keywords (symbols beginning with
:) is automatically bound
to itself in these modules.
(see Keywords, for the details.)
keyword module doesn’t export those bindings, while
gauche.keyword does. The former is intended to be
used internally; the programmer need to know the latter.
If you use the default module inheritance,
you don’t need to use this module, since
keyword module is included in the inheritance chain.
If you don’t inherit
gauche module, however, importing the
gauche.keyword module gives you access to the keywords without quotes.
For example, R7RS programs
and libraries would require either
(import (gauche keyword))
(import (gauche base)) (the latter inherits
gauche.keyword), or you have to quote all keywords.
The following R7RS program imports
gauche.base; it makes gauche
built-in identifiers, and all self-bound keywords, available:
;; R7RS program (import (scheme base) (gauche base)) ; import gauche builtins and keywords ;; You can use :directory without quote, for it is bound to itself. (sys-exec "ls" '("ls" "-l") :directory "/")
If you use more sophisticated import tricks, however, keep in mind
that keywords are just imported symbols by default.
The following code imports
Gauche builtin identifiers with prefix
gauche/. That causes
keywords, imported via inheritance, also get the same prefix; if
you don’t want to bother adding prefix to all keywords or
quote them, import
;; R7RS program (import (scheme base) (prefix (gauche base) gauche/) ; use gauche builtin with gauche/ prefix (gauche keyword)) ; imports keywords ;; Without importing gauche.keyword, ;; you need to write ':directory (gauche/sys-exec "ls" '("ls" "-l") :directory "/")