Skip to main content

MODULE Structure

modulename [ ( parameters ) ] := MODULE [ ( inherit ) ] [, VIRTUAL ] [, LIBRARY(interface) ] [, FORWARD ]

members;

END;

modulenameThe ECL definition name of the module.
parametersOptional. The parameters to make available to all the definitions.
inheritA comma-delimited list of INTERFACE or abstract MODULE structures on which to base this instance. The current instance inherits all the members from the base structures. This may not be a passed parameter.
membersThe definitions that comprise the module. These definitions may receive parameters, may include actions (such as OUTPUT), and may use the EXPORT or SHARED scope types. These may not include INTERFACE or abstract MODULEs (see below). If the LIBRARY option is specified, the definitions must exactly implement the EXPORTed members of the interface.
VIRTUALOptional. Specifies the MODULE defines an abstract interface whose definitions do not require values to be defined for them.
LIBRARYOptional. Specifies the MODULE implements a query library interface definition.
interfaceSpecifies the INTERFACE that defines the parameters passed to the query library. The parameters passed to the MODULE must exactly match the parameters passed to the specified interface.
FORWARDOptional. Delays processing of definitions until they are used. Adding ,FORWARD to a MODULE delays processing of definitions within the module until they are used. This has two main effects: It prevents pulling in dependencies for definitions that are never used and it allows earlier definitions to refer to later definitions. Note: Circular references are still illegal.

The MODULE structure is a container that allows you to group related definitions. The parameters passed to the MODULE are shared by all the related members definitions. This is similar to the FUNCTION structure except that there is no RETURN.

Definition Visibility Rules

The scoping rules for the members are the same as those previously described in the Definition Visibility discussion:

  • Local definitions are visible only through the next EXPORT or SHARED definition (including members of the nested MODULE structure, if the next EXPORT or SHARED definition is a MODULE).

  • SHARED definitions are visible to all subsequent definitions in the structure (including members of any nested MODULE structures) but not outside of it.

  • EXPORT definitions are visible within the MODULE structure (including members of any subsequent nested MODULE structures) and outside of it .

Any EXPORT members may be referenced using an additional level of standard object.property syntax. For example, assuming the EXPORT MyModuleStructure MODULE structure is contained in an ECL Repository module named MyModule and that it contains an EXPORT member named MyDefinition, you would reference that definition as:

MyModule.MyModuleStructure.MyDefinition

MyMod := MODULE
  SHARED x := 88;
  y := 42;
  EXPORT InMod := MODULE //nested MODULE
    EXPORT Val1 := x + 10;
    EXPORT Val2 := y + 10;
  END;
END;

MyMod.InMod.Val1;
MyMod.InMod.Val2;

MODULE Side-Effect Actions

Side-effect Actions are allowed in the MODULE only by using the WHEN function, as in this example:

//An Example with a side-effect action 
EXPORT customerNames := MODULE 
  EXPORT Layout := RECORD 
    STRING20 surname;  
    STRING10 forename; 
    INTEGER2 age := 25; 
  END; 
  Act := OUTPUT('customer file used by user <x>'); 
  EXPORT File := WHEN(DATASET([{'x','y',22}],Layout),Act); 
END; 
BOOLEAN doIt := TRUE : STORED('doIt'); 
IF (doIt, OUTPUT(customerNames.File));
//This code produces two results: the dataset, and the string

Concrete vs. Abstract (VIRTUAL) Modules

A MODULE may contain a mixture of VIRTUAL and non-VIRTUAL members. The rules are:

  • ALL members are VIRTUAL if the MODULE has the VIRTUAL option or is an INTERFACE

  • A member is VIRTUAL if it is declared using the EXPORT VIRTUAL or SHARED VIRTUAL keywords

  • A member is VIRTUAL if the definition of the same name in the inherited module is VIRTUAL.

  • Some members can never be virtual -- RECORD structures.

All EXPORTed and SHARED members of an inherited abstract module can be overridden by re-defining them in the current instance, whether that current instance is abstract or concrete. Overridden definitions must exactly match the type and parameters of the inherited members. Multiple inherited interfaces may contain definitions with the same name if they are the same type and receive the same parameters, but if those inherited members have different values defined for them, the conflict must be resolved by overriding that member in the current instance.

LIBRARY Modules

A MODULE with the LIBRARY option defines a related set of functions meant to be used as a query library (see the LIBRARY function and BUILD action discussions). There are several restrictions on what may be included in a query library. They are:

  • It may not contain side-effect actions (like OUTPUT or BUILD)

  • It may not contain definitions with workflow services attached to them (such as PERSIST, STORED, SUCCESS, etc.)

It may only EXPORT:

  • Dataset/recordset definitions

  • Datarow definitions (such as the ROW function)

  • Single-valued and Boolean definitions

And may NOT export:

  • Actions (like OUTPUT or BUILD)

  • TRANSFORM functions

  • Other MODULE structures

  • MACRO definitions

Example:

EXPORT filterDataset(STRING search, BOOLEAN onlyOldies) := MODULE
  f := namesTable; //local to the "g" definition
  SHARED g := IF (onlyOldies, f(age >= 65), f);
          //SHARED = visible only within the structure
  EXPORT included := g(surname != search);
  EXPORT excluded := g(surname = search);
          //EXPORT = visible outside the structure
END;
filtered := filterDataset('Halliday', TRUE);
OUTPUT(filtered.included,,NAMED('Included'));
OUTPUT(filtered.excluded,,NAMED('Excluded'));
       
//same result, different coding style:
EXPORT filterDataset(BOOLEAN onlyOldies) := MODULE
  f := namesTable;
  SHARED g := IF (onlyOldies, f(age >= 65), f);
  EXPORT included(STRING search) := g(surname <> search);
  EXPORT excluded(STRING search) := g(surname = search);
END;
filtered := filterDataset(TRUE);
OUTPUT(filtered.included('Halliday'),,NAMED('Included'));
OUTPUT(filterDataset(true).excluded('Halliday'),,NAMED('Excluded'));
          
          
//VIRTUAL examples
Mod1 := MODULE,VIRTUAL //a fully abstract module
  EXPORT val := 1;
  EXPORT func(INTEGER sc) := val * sc;
END;
         
Mod2 := MODULE(Mod1) //instance
  EXPORT val := 3; //a concete member, overriding default value
                   //while func remains abstract
END;
     
Mod3 := MODULE(Mod1) //a fully concete instance
  EXPORT func(INTEGER sc) := val + sc; //overrides inherited func
END;
OUTPUT(Mod2.func(5)); //result is 15
OUTPUT(Mod3.func(5)); //result is 6

//FORWARD example
EXPORT MyModule := MODULE, FORWARD
  EXPORT INTEGER foo := bar;
  EXPORT INTEGER bar := 42;
END;

MyModule.foo;

See Also: FUNCTION Structure, Definition Visibility, INTERFACE Structure, LIBRARY, BUILD