From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Marius Vollmer Newsgroups: gmane.lisp.guile.devel Subject: Re: What replaces scm_register_module_xxx (Doc update?) Date: 12 Aug 2002 01:20:30 +0200 Sender: guile-devel-admin@gnu.org Message-ID: <87hei1dltt.fsf@zagadka.ping.de> References: <20020808134824.GB23831@www> <20020808102103.021cdc0c.dsmith@altustech.com> <874re5mnfs.fsf@raven.i.defaultvalue.org> <20020808161958.GA24162@www> <20020809100046.GB25104@www> <87u1m26aff.fsf@zagadka.ping.de> NNTP-Posting-Host: localhost.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1029108027 1445 127.0.0.1 (11 Aug 2002 23:20:27 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Sun, 11 Aug 2002 23:20:27 +0000 (UTC) Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 17e20V-0000N4-00 for ; Mon, 12 Aug 2002 01:20:24 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 17e21D-0002yv-00; Sun, 11 Aug 2002 19:21:07 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 17e20e-0002uy-00 for guile-devel@gnu.org; Sun, 11 Aug 2002 19:20:32 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 17e20a-0002u1-00 for guile-devel@gnu.org; Sun, 11 Aug 2002 19:20:31 -0400 Original-Received: from dialin.speedway42.dip45.dokom.de ([195.138.42.45] helo=zagadka.ping.de) by monty-python.gnu.org with smtp (Exim 4.10) id 17e20Z-0002tw-00 for guile-devel@gnu.org; Sun, 11 Aug 2002 19:20:27 -0400 Original-Received: (qmail 6957 invoked by uid 1000); 11 Aug 2002 23:20:30 -0000 Original-To: guile-devel@gnu.org In-Reply-To: <87u1m26aff.fsf@zagadka.ping.de> Original-Lines: 337 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 Errors-To: guile-devel-admin@gnu.org X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Developers list for Guile, the GNU extensibility library List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.lisp.guile.devel:1063 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.devel:1063 Marius Vollmer 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