unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Marius Vollmer <mvo@zagadka.ping.de>
Subject: Re: What replaces scm_register_module_xxx (Doc update?)
Date: 12 Aug 2002 01:20:30 +0200	[thread overview]
Message-ID: <87hei1dltt.fsf@zagadka.ping.de> (raw)
In-Reply-To: <87u1m26aff.fsf@zagadka.ping.de>

Marius Vollmer <mvo@zagadka.ping.de> writes:

> rm@fabula.de writes:
> 
> > Should this be documented soon?
> 
> Will do.

Ok, I started but I got distracted into writing don yet another module
system proposal.  Please have a look.  It is not finished, but I think
one can already see where it is heading.  It is based on
scheme-modules.texi.


@node The Guile module system
@section The Guile module system

The Guile module system extends the concept of environments, discussed
in the previous section, with mechanisms to define, use and customise
sets of bindings.

In 1996 Tom Lord implemented a full-featured module system for Guile which
allows loading Scheme source files into a private name space.  This system has
been in available since at least Guile version 1.1.

For Guile version 1.6.0 and later, the system has been improved to have better
integration from C code, more fine-grained user control over interfaces, and
documentation.

Although it is anticipated that the module system implementation will
change in the future, the Scheme programming interface described in this
manual should be considered stable.  The C programming interface is
considered relatively stable, although at the time of this writing,
there is still some flux.

The following sections will explain the Guile module system in detail,
from an interactive point of view.  That is, the behavior of the
module system is defined in terms of run-time data structures and the
operations on them.  The operations include the high-level ones like
@code{define-module} that are used more like declarative statements as
well as lower level operations like @code{module-lookup}.

@c fixme: Review: Need better C code interface commentary.

@menu
* Finding Modules::             How modules are found.
* General Information about Modules::  Guile module basics.
* Using Guile Modules::         How to use existing modules.
* Creating Guile Modules::      How to package your code into modules.
* More Module Procedures::      Low-level module code.
* Module System Quirks::        Strange things to be aware of.
* Included Guile Modules::      Which modules come with Guile?
@end menu

@node Finding Modules
@subsection Finding Modules

A Guile module is a data structure with the features described in the
following sections.  You can work directly with the data structure in
your programs, but normally you refer to them indirectly via the
familiar hierachical names like @code{(ice-9 popen)}.

There is a global mapping from names to module objects.  You can
manipulate this mapping with the settable function @code{find-module}.
You can find the name of a module with the function
@code{module-name}.

Normally, modules are created as a side-effect of loading and
executing a file.  The file might contain a @code{define-module} that
will install a new module, or it might not.  Thus, files and modules
are only loosely coupled.  However, there is a convention that maps
module names to file names and this convention allows Guile to
automatically load and execute a file when a certain module is
requested but has not been registered yet.

The function @code{load-module} implements this mapping and
@code{resolve-module} is an extended version of @code{find-module}
that uses @code{load-module} for missing modules.  Thus,
@code{resolve-module} is the most common function to use when looking
for a module.

@deffn Procedure find-module name
@deffnx Setter (set! (find-module name) module)
The procedure @code{find-module} returns the module that has most
recently been registered with the name @var{NAME}.  When no module has
been registered under @var{NAME}, return @code{#f}.

Note that @code{find-module} will not automatically load modules.  Use
@code{resolve-module} or @code{load-module} for that.

Setting this procedure will register @var{module} under the name
@var{name}.  When @var{module} is @code{#f}, any registration for
@var{name} is removed.

A @var{name} must be a list of symbols like @code{(ice-9 popen)}.

When a module is registered, the name is remembered in it so that
@code{module-name} can return it.  When a module is removed from the
global mapping (because it is replaced by another module or by
@code{#f}), its remembered name is not changed.
@end deffn

@deffn Procedure module-name module
@deffnx Setter (set! (module-name module) name)
Return the remembered name of @var{module}.  This is not necessarily
the name that can be used to find this module with @code{find-module}.
See @code{find-module} for details.  The initial name of a module is
@code{#f}.

Setting this procedure will change the remembered name.  It will not
change the global mapping that is consulted by @code{find-module}.

The remembered name of a module is mostly intended for debugging
purposes.
@end deffn

@deffn Procedure load-module name
Load the file that is supposed to define the module named by
@var{name}, a list of symbols.

The name of the file to load is constructed by concatenating the name
elements with slashes between the elements and appending a number of
file name extensions from the list @code{%load-extensions}
(@pxref{Loading}).  The resulting file name is then searched in all
directories in the variable @code{%load-path} (@pxref{Install
Config}).  For example, the @code{(ice-9 popen)} module would result
in the filename @code{ice-9/popen.scm} and searched in the
installation directories of Guile and in all other directories in the
load path.  The first file that is found by the above procedure is
loaded.  When no file is found, signal an error.

After the the file is loaded, the result of @code{(find-module
@var{name})} is returned when it is non-@code{#f}.  Else signal an
error.
@end deffn

@deffn Procedure resolve-module name
Find the module named @var{name}, loading it via @code{load-module}
when it is not yet registered.  When the module can not be found,
signal an error.
@end deffn


@node General Information about Modules
@subsection General Information about Modules

A Guile module can be thought of as a collection of named variables
and macros.  More precisely, it is a mapping of symbols (names) to
Scheme objects.  Such an association of a symbol with an object is
also called a @dfn{binding}, and one says that the symbol is
@dfn{bound} to the object in a specific module.  Symbols can only be
bound to two kinds of objects: variables or macro transformers.

This is a crucial point; when you evaluate @code{(define foo 12)} in a
module, then the symbol @code{foo} is not bound directly to @code{12}.
Rather, @code{foo} is bound to a variable (@pxref{Variables}) and the
value of that variable is set to the value @code{12}.  Likewise, when
you define a macro, the symbol is bound to a macro transformer object
instead of to a variable.  (Actually, Guile wont do the latter
currently, but will do so in the next release.)

@c I think the following paragraph is confusing here, especially
@c given that there are objects called ``envrionments'' in Guile
@c that are really modules. - mvo
@c
@c An environment is a mapping from identifiers (or symbols) to
@c locations, i.e., a set of bindings.  There are top-level environments
@c and lexical environments.  Environment in which a lambda is excuted is
@c remembered as part of its definition.

You can only add to the set of bindings of a module, you can not
remove bindings.  Also, you can only have a single binding for each
symbol in the set.  As a consequence, once you have added a local or
imported binding to a module, it can not be changed.  Attempting to
bind a symbol to the same object that it is already bound to is
silently ignored.

These rules ensure that a module can only evolve in a simple manner.
Once you have looked up a binding in a module, you can be sure that it
remains valid and that all lookups with the same symbol in a module
will return the same binding.  When you need to make changes to a
module that are not allowed by these rules, you must abandon the old
module and create a new one.  Modules that use the old module in some
way need to be reconstructed as well, and so on.  See @pref{FIXME} for
more information about this.

When Guile executes or compiles some code, it does this always in the
context of a module.  That module is called the @dfn{current module}.
Set settable procedure @code{current-module} can be used to access the
current module.  The global identifiers of the executed or compiled
code are looked up by finding the object that is bound to the
identifier symbol in the current module.  In certain contexts, the
object must be a variable so that it can be referenced or set, in
others, it is also allowed to be a macro transformer which is then used
to expand the evaluated form.

Execution of a @code{define} form can add a new variable binding to
the current module.  When the symbol in the @code{define} form is
already bound to a variable, the binding itself is not changed, only
the value of the variable.  When the symbol is bound but not to a
variable, an error is signalled.

Execution of @code{define-macro} works similar, but for macro
transformers instead of variables.

To access bindings from another module, the desired bindings are
simply copied into the accessing module.  There are several ways to
select which bindings to copy exactly and how to transform the symbols
on the way.  Ultimately, however, imported bindings are added just
like local bindings.

You can access all bindings in a module; there are no strictly private
bindings that you are prohibited from accessing.  However, each module
has a list of @dfn{exported symbols} that it offers as its public
interface.  Usually, one just imports the bindings belonging to the
exported symbols.

You can add to the list of exported symbols with an @code{export}
statement.  Symbols can be removed with @code{unexport}.  Changes to
the list of exported symbols have no immediate consequences in other
modules, however.  The list is only consulted at the time of
importing, if at all.


@node Using Guile Modules
@subsection Using Guile Modules

Accessing bindings from another module is called @dfn{using} that
module.  On a low level, it consists of determining which bindings to
access by building a list of symbols that name these bindings in the
accessed module, and building another list of symbols that determine
for each binding under which name it should be recorded in the
accessing module.

The procedure @code{module-import} can then be used to add the new
bindings to the accessing module.  After the bindings have been added
to the module, all memory is lost about where they came from.

A common way of using a module is to just import all exported bindings
with their original names.  This, and also more sophisticated
arrangements, can be conveniently expressed with a @code{use-modules}
statement.  Executing a @code{use-modules} statement may include
locating and loading code for a given module if that code has not yet
been loaded.

An @dfn{interface specification} in a @code{use-modules} statement has
one of two forms.  The first variation is simply to name the module,
in which case its exported bindings are imported with their original
names.  For example:

@smalllisp
(use-modules (ice-9 popen))
@end smalllisp

Here, the interface specification is @code{(ice-9 popen)}, and the
result is that the current module now has access to @code{open-pipe},
@code{close-pipe}, @code{open-input-pipe}, and so on (@pxref{Included
Guile Modules}).

Note in the previous example that if the current module had already
defined @code{open-pipe}, adding the binding from @code{(ice-9 popen)}
would have resulted in an error.  For this reason (and others), there
is a second variation of interface specification that not only names a
module to be accessed, but also selects bindings from it and renames
them to suit the current module's needs.  For example:

@smalllisp
(use-modules ((ice-9 popen)
              :select ((open-pipe . pipe-open) close-pipe)
              :renamer (symbol-prefix-proc 'unixy:)))
@end smalllisp

Here, the interface specification is more complex than before, and the
result is that a custom interface with only two bindings is created and
subsequently accessed by the current module.  The mapping of old to new
names is as follows:

@c Use `smallexample' since `table' is ugly.  --ttn
@smallexample
(ice-9 popen) sees:             current module sees:
open-pipe                       unixy:pipe-open
close-pipe                      unixy:close-pipe
@end smallexample

This example also shows how to use the convenience procedure
@code{symbol-prefix-proc}.

@c begin (scm-doc-string "boot-9.scm" "symbol-prefix-proc")
@deffn {Scheme Procedure} symbol-prefix-proc prefix-sym
Return a procedure that prefixes its arg (a symbol) with
@var{prefix-sym}.
@c Insert gratuitous C++ slam here.  --ttn
@end deffn

@c begin (scm-doc-string "boot-9.scm" "use-modules")
@deffn syntax use-modules spec @dots{}
Resolve each interface specification @var{spec} into a set of bindings
and add them to the current module.  The return value is unspecified.

The first variant of @var{spec} is just

@smalllisp
 MODULE-NAME
@end smalllisp

where @var{module-name} is a list of symbols that names a module whose
exported bindings are added to the current module with their original
names.  The module named by @var{module-name} is loaded as with
@code{resolve-module} when it has not been registered already.

The second variant of @var{spec} is

@smalllisp
 (MODULE-NAME [:select SELECTION] [:renamer RENAMER])
@end smalllisp

As before, @var{module-name} is a list of symbols that is used to find
the module that is to be accessed.  The optional @var{selection}
parameter is a list of selection-specs and the optional @var{renamer}
is a procedure that takes a symbol and returns a new one that should
be used in its place as the name of a binding.  A selection-spec is
either a symbol or a pair of symbols @code{(ORIG . SEEN)}, where
@var{orig} is the name in the accessed module and @var{seen} is the
name in the accessing module.  The symbol @var{seen} is also passed
through @var{renamer}.

When @code{selection} is omitted, it defaults to the list of exported
symbols of @var{module-name}.  When @code{rename} is omitted, it
defaults to the identity function (i.e., the bindings are not
renamed).  Thus, when both are omitted, the effect is the same as with
the first var{spec} form.

A error is signalled when @var{module name} is not resolvable.
@end deffn

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


  reply	other threads:[~2002-08-11 23:20 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-08 13:48 What replaces scm_register_module_xxx (Doc update?) rm
2002-08-08 14:21 ` Dale P. Smith
2002-08-08 14:23   ` Dale P. Smith
2002-08-08 14:31   ` Rob Browning
2002-08-08 16:19     ` rm
2002-08-08 17:59       ` Dale P. Smith
2002-08-08 18:24         ` rm
2002-08-08 20:26       ` Marius Vollmer
2002-08-08 21:28       ` Neil Jerram
2002-08-09 15:36         ` rm
2002-08-17 11:59           ` Neil Jerram
2002-08-19 19:05             ` rm
2002-08-09  8:47       ` Matthias Koeppe
2002-08-09 10:00         ` rm
2002-08-09 11:29           ` Matthias Koeppe
2002-08-09 13:23             ` rm
2002-08-10 14:44           ` Marius Vollmer
2002-08-11 23:20             ` Marius Vollmer [this message]
2002-08-17  8:09               ` Dirk Herrmann
2002-08-17 11:05                 ` Neil Jerram
2002-08-24  8:08                   ` Dirk Herrmann
2002-08-26 21:45                     ` Neil Jerram
2002-08-26 22:04                     ` Marius Vollmer
2002-08-21 19:35                 ` Marius Vollmer
2002-08-13  0:40             ` Marius Vollmer
2002-08-17 22:37               ` Dale P. Smith

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87hei1dltt.fsf@zagadka.ping.de \
    --to=mvo@zagadka.ping.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).