REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 26-Apr-2010 Edit History  

REBOL 3 Concepts: Modules: Loading Modules


Summary of methods

There are a few ways to load modules:

needsis a block that you can put in your program header to specify the modules your program wants loaded to run.
importcalled in your code to load a module from a file, URL, or name.
docalled in your code with a module file or URL.
moduledirectly creates modules from blocks that contain a module definition.
makelower level module creation function. Takes a block that contains a module definition.

Specifying modules in headers

If your program requires one or more modules, you can specify them in your program's header block using the needs field.

For example:

    Title: "Super Web Site"
    Author: "John Adams"
    Needs: [mysql http-server]

db: open-db %my-database.sql

When this file is loaded, the header is examined, the mysql and http-server modules are imported, then the main body of the program is evaluated.

Once a module has been imported, all of it's exported functions and other values are available to be used by your code. In the example above, the open-db function is defined by the mysql module.

Types of module identifiers

A few types of module identifiers are allowed, and are summarized in this table:

Datatype What Action
word! module by name search multiple locations for the module
file! local file path of module must be found at that location
url! Internet location of module must be found at that location

Searching for modules

When the module name is a word, REBOL will search for the module in a few locations.

Here's what happens:

  1. The name is used to check the system/modules list to see if the module has already been loaded. If so, it will not be loaded again.
  2. The module name is converted to a file name (with a .r suffix is added).
  3. Local directories and Internet addresses are searched for the module. The order of the search is determined by the system/options/module-paths block.


Here is an example that uses all three types of module identifiers:

Needs: [

In this example:

Specifying a module version

If your program requires specific module versions, they can be specified as well:

Needs: [
    mysql 2.3.0
    http-server 1.0.1

For the mysql module a version of 2.3.0 or greater is required. For http-server the version must be 1.0.1 or greater.

Versions are tuples

Version numbers are always tuple! datatypes so be sure to provide at least three parts of the version number, otherwise it's not a tuple, it's a decimal! number.

Also note that if a version number appears before any module name, it is assumed to be the REBOL system version. So:

Needs: [3.0.2 mysql 2.3.0 http-server 1.0.1]

indicates that the script needs REBOL 3.0.2. If the REBOL version is less, an error message will be displayed.

Validating modules with a hash checksum

In addition to specifying a module name and version, you can also specify that modules be validated using a hash checksum.

This is a type of integrity check. It is done to verify that the module contents have not been modified in any way (but, read the note below, because it's not perfect.)

Needs: [
    mysql 1.2.3 #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3}
    http-server 1.0.1 #{8E67416A43298507CC22135E28233F4B9C27E75D}

Here the two modules will be located and read in to memory. The hash checksums will be computed for their source code (not including the header) and compared to the header. If they are the same, the load continues. If not, an error is displayed.

Super-secure applications

REBOL uses the more secure SHA-1 hashing method rather than MD5. However, it must be noted that SHA-1 is not perfect.

For applications that require maximal module integrity (nuclear submarines, power plants, automated cat food dispensers), you should download the modules files, manually validate them, then load them as local file modules, not from the Internet.

See SHA Hashing for more information.

Importing modules directly

You can also import modules directly using the import function. This function follows the same rules as the needs field of a program header, as explained above.

For example, you can write:

import 'mysql

and the system will search for the mysql module, using the method described above.

You can also use a filename or URL for the module identifier:

import %mysql.r


And, you can import from a block of modules (which is in fact a valid needs block):

import [mysql db-gui http-server]

Return value

When successful, the import function returns a module! datatype as its result.

This allows you to write:

mysql: import 'mysql

Now, the mysql variable can be used to refer to values within the mysql module.

For example the module value is used here to reference a function:

mysql/open-db %my-database.sql

See below for more.

Useful refinements

Like the header needs field, the import function also lets you specify a version and a checksum.

These are all supported:

import/version mysql 1.2.3

import/check mysql #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3}

import/version/check mysql 1.2.3 #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3}

When to use IMPORT

The benefit of using the import function compared to the needs header field is that the arguments can be variables.

A basic example is:

mod: 'mysql
import mod

Or, something like:

mod-list: [
    mysql 1.2.3
    db-gui 2.4.5
    http-server 1.0.1

import mod-list

Doing modules

Another method of importing modules is supported. If you use do on a module file, it will also be imported. This is provided as a convenience, because do has been used in REBOL for years as a way to load and initialize additional functions and values.

For example, writing:

do %mysql.r

is equivalent to:

import %mysql.r

But note that:

import 'mysql

is not the same as:

do 'mysql

because do of a word simply returns the value word.

Note also that do does not support the version and checksum refinements found in the import function.

Explicit references into modules

What happens when an imported module uses the same global variable name as one you define in your program?

Here is an example. A program loads a module that exports the function select-data:

import %database.r

But, the program defines it's own function:

select-data: func [database selector] ...

Both of the functions can't use the same name as global variables.

This situation can be solved by using the result of the import function as a way to reference its specific values.

Here's an example:

db-mod: import %database.r

; Define our own local function:
select-data: func [database selector] ...

; To use the module's function:
db-mod/select-data ...

This is identical to how you reference a field of an object.

Dynamic (embedded) modules

Modules are also allowed to be created dynamically by a program. This is normally done for two reasons:

  1. The modules are used to isolate separate parts of a program's namespace (similar to how objects have been used in the past).
  2. The program has been constructed by combining multiple source files, some of which are modules. The modules are within the body of the file, rather than loaded as separate files at run time.

For more about these types of modules, see modules: defining modules.

  TOC < Back Next > - WIP Wiki Feedback Admin