There are a few guiding principles behind the design of Indu. Keep the language small with only a few constructs is one. Encourage building programs by assembling small pieces into larger is another.
The first of those principles requires that Indu support modules. It does that with the
include from <uri> construct. The second requires that the implementation of these module either re-uses or replaces an existing construct. This is a challenge to get right as there aren’t a lot of good examples of modules. Most languages just use simple textual replacement: from C’s
#include to Ruby’s
require. OCaml’s modules are well-regarded, however, as they are first-class and allow parameterisation.
How should Indu provide module-like constructs without the support of a type system as required by OCaml’s Functor approach, and with more structure than simple text pasting? The approach I have taken is to re-use mixins.
The top-level of every Indu source unit implicitly defines an unnamed object. When one source unit
includes another source unit, the object defined by the second is mixed into the one defined by the first. There are two implications.
- As mixins already support parameters,
includecould be parameterised. This could parameterise the included module. That would give something a lot like OCaml’s Functors.
- This provides no support for name clashes. Any names included from one module will be overwritten by any identical names defined in the current module.
The first would require some new syntax to add parameters to an
include from /indu/blog with (title: "overwatering")
The second could be dealt with by convention: if every source unit defined a single object and put all constructs in there. But, that means if you ever want to include a module it’ll need to be one structured like that. And clashes will still occur. And it means that you wouldn’t be able to use an existing application as a module: it’d needed to be separated into an application source unit and a module source unit first.
And convention means another thing to learn, which means one more barrier to getting started.
The answer is to include some syntax to name the module that is being included. Construct an object with that name, as an attribute of the current top-level module, and mixin the included module there. The syntax is obvious.
include Blog from /indu/blog with (title: "overwatering")