Modules

Modules allow you to organise your code into nested namespaces. A module can contain types, functions and other modules.

Reactive.Module('Text', function () {

  Reactive.Function('Trim', function () {
    var s = Reactive.Argument(Text);
    return Reactive.Calculate(function () { return String(Reactive.Value(s)).trim(); });
  });

  Reactive.Function('Upper', function () {
    var s = Reactive.Argument(Text);
    return Reactive.Calculate(function () { return String(Reactive.Value(s)).toUpperCase(); });
  });

});
Defining a Text module with two functions

Defining a module

Call Reactive.Module(name, body) and, inside the body, declare the functions and types that belong together. The name becomes a top-level global, such as Text above, and everything you declare in the body lands under it. Nest a Reactive.Module call inside another and the namespaces nest with it, so Maths.Real.Add is a module within a module.

Using a module

Once declared, a module is a top-level global, ready to use, so you reach its operations by their dotted path and call them like any other function, passing reactive values in and getting reactive values back.

var name = Reactive.State(Text)('ada');

Content.Text(Text.Upper(name));   // ADA — updates when name does
Calling a module function by its dotted path

Reading the dotted names is how you navigate the framework: the same path that groups an operation is the path you call it by.

Overriding a module

Modules are open. Call Reactive.Module again with a name that already exists and you reopen that same namespace: new declarations are added, and a function declared a second time overwrites the first. That is all it takes to swap one operation for another implementation while every call site stays unchanged.

Reactive.Module('Text', function () {     // reopen the existing namespace
  Reactive.Function('Upper', function () {   // replace one operation
    var s = Reactive.Argument(Text);
    return Reactive.Calculate(function () { return String(Reactive.Value(s)).toLocaleUpperCase(); });
  });
});
Reopening a module to override a function

Because operations are reified, the implementation behind a name can change while the code that calls it stays the same. Supplying a whole module of replacements underneath a program is exactly how a driver re-targets the same definition, into the page, a PDF, or a 3-D scene, unchanged.