[ALLY] REBOL Modules Doc
From: carl::rebol::com at: 31-Jul-2000 13:24
--=====================_951290263==_
Content-Type: text/plain; charset="us-ascii"
Jim just reminded me that I promised to say a few words about REBOL Modules here on the
ally list. I'll do better than that: Here's a short document that describes REBOL modules.
Take a look.
-Carl
--=====================_951290263==_
Content-Type: text/html; charset="us-ascii"
Content-Disposition: attachment; filename="modules.html"
<html><title>REBOL Modules
</title><body><font face="arial,helvetica"><h2>REBOL Modules
</h2></font><p><b><pre> REBOL Enhancement Proposal: REP002
Version: 1.0.1
Author: Carl Sassenrath
</pre></b>
<HR><P><font face="arial,helvetica"><h3>Contents:</h3></font><p><blockquote><font face="arial,helvetica"><B><A
HREF="#section-1">1. Overview
</A><BR><A HREF="#section-2">2. Context Binding
</A><BR><A HREF="#section-3">3. Creating Modules
</A><BR><A HREF="#section-4">4. Module Hierarchy
</A><BR><A HREF="#section-5">5. Module Reflection
</A><BR></B></font></blockquote><HR><A NAME="section-1"></A><p><font face="arial,helvetica"><h3>1.
Overview
</h3></font><p><blockquote>A REBOL module is an independent context - a namespace. Modules
are
similar to objects in that they associate variables with values.
However, modules extend beyond objects in the following ways:
<p>
<ul><li>You cannot access the variables of a module unless they have been
explicitly exported nor can you access the word list of a module (as in the
first of an object).
<p>
<li>Modules include descriptive blocks that define the module title, date,
version, and other reflective information.
<p>
<li>You can create modules that act as a global environment, shielding
the words above it from direct access.
<p>
<li>Your scripts can be defined as modules. This is specified by script
headers.
<p>
</ul>Also note that like objects, modules can be nested to allow nested
contexts.
<p>
Modules should not be confused with components, which are the plug-in
feature-sets of REBOL. However, a component may include one or more
modules.
<p>
</blockquote><HR><A NAME="section-2"></A><p><font face="arial,helvetica"><h3>2. Context
Binding
</h3></font><p><blockquote>The module design allows for varying degrees of context binding.
You can
control how free words (non-locals) are bound.
<p>
<blockquote><table cellspacing=0 border=0><tr><td valign="top" width="80"><B>Strict</B></td><td
valign="top">Bind every word to the local frame. The binder will extend
the local frame as much as necessary to hold all words. The module
is completely encapsulated.
</td></tr>
<tr><td valign="top" width="80"><B>User</B></td><td valign="top">Every word that is not
defined in a previous context will be
bound to the local context. This allows users to get to REBOL's
predefined words but have all new words bound to the local context. This
is how most scripts will operate by default.
</td></tr>
<tr><td valign="top" width="80"><B>Explicit</B></td><td valign="top">An explicit list
of local words is provided for the module.
All other free words will be bound to previous frames.
</td></tr>
<tr><td valign="top" width="80"><B>Implied</B></td><td valign="top">Words that use SET
notation at the top block level of the
module will be local. All other are bound above. This is the same as
object instance variables. This is the default for the MAKE module
function.
</td></tr>
</table></blockquote></blockquote><HR><A NAME="section-3"></A><p><font face="arial,helvetica"><h3>3.
Creating Modules
</h3></font><p><blockquote>Modules can be created with either the MAKE function or by
evaluating
scripts that contain module words in their headers.
<p>
To create a module with MAKE, you must supply a module interface
specification block and a body block. The MAKE has the general form:
<p>
<b><pre> new: make spec body
</pre></b>
The value returned from MAKE is the new module and it can be assigned
to a variable, passed to another function, or returned as the result
of a function.
<p>
<p><font face="arial,helvetica"><i><h4>3.1. Interface Specification
</h4></i></font><p>The specification block is a header that is similar to that used with
scripts. It contains a title, date, version, author, and other fields of
a header. In addition, there are fields that are unique to modules:
<p>
<blockquote><table cellspacing=0 border=0><tr><td valign="top" width="80"><B>export</B></td><td
valign="top">Provides a block of words that define the variables that can be
accessed externally from the module.
</td></tr>
<tr><td valign="top" width="80"><B>import</B></td><td valign="top">Provides an optional
block of imported words. When this block
has been provided, no external words are bound within the module other
than those that have been specified. This allows you to limit the
module's access to REBOL functions.
</td></tr>
<tr><td valign="top" width="80"><B>local</B></td><td valign="top">Specifies an optional
block that explicitly defines the local
variables of the module. If this is not specified, then the local
variables will be defined by their top level block set operations (as
done with objects).
</td></tr>
<tr><td valign="top" width="80"><B>module-options</B></td><td valign="top">special flags
used to control the level of binding for
the module. For instance, the LOCAL attribute forces free variables that
are not bound in any frame to be bound in the module, not bound in parent
contexts. The USER attribute makes the module a top level frame (like a
user frame).
</td></tr>
</table></blockquote>Here is an example of a simple module definition:
<p>
<b><pre> example: make module! [
title: "Example module"
version: 1.0.0
export: [do-it]
][
data: [block of local data]
do-it: does [probe data]
]
</pre></b>
The do-it function can now be called with:
<p>
<b><pre> example/do-it
</pre></b>
But, you cannot access the data. This line would cause an error:
<p>
<b><pre> example/data
** Script Error: Invalid path value: data
** Where: example/data
</pre></b>
<p><font face="arial,helvetica"><i><h4>3.2. Scripts as Modules
</h4></i></font><p>For convenience, a script can also be defined as a module. This is
done
by specifying the module description as part of the script header:
<p>
<b><pre> REBOL. [
title: "Script Module"
version: 1.0.0
module: 'script-module
export: [do-it]
]
...
</pre></b>
When the script is evaluated, it will be evaluated as a module. All of
its free words (globals) will be local to the module.
<p>
<p><font face="arial,helvetica"><i><h4>3.3. Variable Definitions
</h4></i></font><p>Within a module, variables are defined as module-local in the same
way that objects define their instance variables. You can write:
<p>
<b><pre> make module! [export [a]] [
a: b: c: d: e: f: none
...
]
</pre></b>
You can explicitly declare the variables that are local to a module
(but you will also need to remember to maintain this list!):
<p>
<b><pre> make module! [export [a] local [a b c d e f]] [
...
]
</pre></b>
All such locals will be set to NONE when the module is created.
<p>
Of course, if the LOCAL module-option is used, then all variables will
be bound locally other than those that are explicitly imported.
<p>
</blockquote><HR><A NAME="section-4"></A><p><font face="arial,helvetica"><h3>4. Module
Hierarchy
</h3></font><p><blockquote>The new module architecture allows an enhanced context structure
for REBOL
and its scripts. Scripts will no longer be bound by default to the
global frame (main-frame). Instead, scripts will be bound to a USER
frame that is created below the main frame. This allows entire scripts
and all of their functions and data to be garbage collected if they are
no longer required.
<p>
This changes the binding process for scripts. The binder looks locally
for a word, then looks up the hierarchy for the name. If the word does
not appear anywhere in the hierarchy, then the module frame is extended
with the new word. Effectively, free variables become module local,
rather than global.
<p>
The hierarchy of module contexts is now defined as:
<p>
<b><pre> ROOT frame (natives, and C code references)
SYSTEM frame (most of the mezz functions)
USER frame (user script)
MODULE frame (sub-scripts or make modules)
</pre></b>
When the USER module-option is used with MAKE, a peer frame is created
to a script. The new module is placed at the USER frame level,
rather than at the MODULE level. This allows you to create scripts
that evaluate scripts in pristine environments. (That is, in the
same environment as your first script.)
<p>
<b><pre>
</pre></b>
</blockquote><HR><A NAME="section-5"></A><p><font face="arial,helvetica"><h3>5. Module
Reflection
</h3></font><p><blockquote>You can obtain the header specification of a module with the
FIRST
function. This will return the header as was used to define the module.
This also allows you to reflectively determine what words are exported by
a module. You can use this to automatically generate documentation about
a module.
<p>
<b><pre> foreach word get in first module 'export [
print word
]
</pre></b>
</blockquote>-End: Makespec 1.4.0</body></html>
--=====================_951290263==_--