[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11 Modules

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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.1 Module semantics

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 always eq? if two have the same name. 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 signalled.

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 define and define-syntax 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 B, you'll see B's binding.

If you import A, then B, then A again, the last import takes precedence; that is, you'll see A's binding.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.2 Modules and libraries

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.

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 use 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, module-name->path and path->module-name, to do mapping for you (see Module introspection, for details).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.3 Defining and selecting modules

Special Form: define-module name body …

Name must be a symbol. If a module named name does not exist, create one. Then evaluates body sequentially in the module.

Special Form: select-module name

Makes a module named name as the current module. It is an error if no module named name exists.

If 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 not affected.

Special Form: with-module name body …

Evaluates body sequentially in the module named name. Returns the last result(s). If no module named name, an error is signalled.

Special Form: current-module

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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.4 Using modules

Special Form: export symbol …

Makes bindings of symbols in the current module available to modules that imports the current module.

Special Form: export-all

Makes all bindings in the current module available to modules that imports it.

Special Form: import module-name …

Makes all exported bindings in the module named module-name available in the current module. The named modules should exist when the compiler sees this special form.

Note that 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.

Macro: use name

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.

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 require and import separately. However, all modules provided with Gauche are arranged so that they can be used by use macro.

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 module-name->path below. The default rule is to replace periods `.' in the name for `/'; 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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.5 Module inheritance

The export-import mechanism doesn't work well in some cases, such as:

You can use module inheritance in these cases.

Macro: extend module-name …

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 scheme module that has only bindings defined in R5RS, hence, after the export form, you can't use 'import' or any other gauche-specific bindings in the module.

If a named module is not defined yet, extend 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 in 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 signalled.

For example, suppose you wrote a library in modules mylib.base, mylib.util and mylib.system. You can bundle those modules into one module by creating a module 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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.6 Module introspection

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.

Builtin Class: <module>

A module class.

Function: module? obj

Returns true if obj is a module.

Function: find-module name

Returns a module object whose name is a symbol name. If the named module doesn't exist, #f is returned.

Function: make-module name &keyword if-exists

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 :error (default), an error is signalled. If it is #f, #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 define-module, import, extend, with-module all takes module names, not modules. It is because module are inherently compile-time structure. 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 section 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 import and extend take 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.

Function: all-modules

Returns a list of all named modules. Anonymous modules are not included.

Function: module-name module
Function: module-imports module
Function: module-exports module
Function: module-table module

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.

If the module exports all symbols, module-exports returns #t.

It is an error to pass a non-module object.

Function: module-parents module
Function: module-precedence-list module

Returns the information of module inheritance. Module-parents returns the modules module directly inherits from. Module-precedence-list returns the module precedence list of module (See section Module inheritance).

Function: global-variable-bound? module symbol

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 global-variable-bound? instead. The reason of change is that because of the name symbol-bound? and 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.

Function: global-variable-ref module symbol &optional default

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 signalled, unless the default argument is provided, in which case it is returned instead.

Function: module-name->path symbol

Converts a module name symbol to a fragment of pathname string (which you use for require and provide).

Function: path->module-name string

Reverse function of module-name->path.

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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11.7 Predefined modules

Several modules are predefined in Gauche.

Builtin Module: null

This module corresponds to the null environment referred in R5RS. This module contains only syntactic bindings of R5RS syntax.

Builtin Module: scheme

This module contains all the binding of null module, and the binding of procedures defined in R5RS.

Note that if you change the current module to null or scheme by select-module, there will be no way to switch back to other modules, since module-related syntaxes and procedures are not visible from null and scheme modules.

Builtin Module: gauche

This module contains all the bindings of scheme module, plus Gauche specific built-in procedures.

Builtin Module: user

This module is the default module the user code is compiled. all the bindings of gauche module is imported.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Shiro Kawai on October, 7 2008 using texi2html 1.78.