A module system for Arc
One of the things that made Perl as popular as it is today, I think, was the ability to extend the language and build third-party libraries easily and minimise conflict with each other. This is something that Arc as it exists today presently lacks, and something that it should eventually have. I suppose Paul Graham left it to evolve naturally, but so far this has not happened to my knowledge.
The existence of a standard module system will also help to ameliorate incompatibility as well: most of the extensions that I’m building into Arcueid should go into their own modules, except for such things as the C99 mathematical functions (sin
, cos
, etc.), additional network I/O functions (e.g. socket
, select
, socket-bind
), etc.: in general things that are logical completions of functionality that is already in the official Arc reference implementation. Things unique to the Arcueid implementation such as the marshalling mechanism (CIEL), the Limbo-inspired thread communication and synchronisation primitives, and so forth, must all go into their own modules to limit pollution of the global namespace with incompatible symbols as far as possible.
The module mechanism would thus also exist in its own module, but special syntax should be provided to support use of the module system in order to facilitate its use. Module support functions, detailed below, are minimal, and all are defined in the top-level module along with all of the standard definitions.
Free variables are qualified as belonging to some module by the qualify function. The :: ssyntax operator expands to make use of the qualify function, e.g. MyModule::some-function
becomes (qualify some-function MyModule)
. ::some-function qualifies some-function
as belonging to the top-level module.
The module
form opens a module, and all unqualified definitions within the module form are created in the namespace created by the module. The values for unqualified free variables are found by first looking in the module’s global symbols, and then searching for a binding of the symbol in the parent module, until the top-level module (where all of the standard symbols are found) is reached. All bindings to unqualified free variables are made against the module’s namespace.
The import
function basically alters the behaviour of free variable binding resolution in all subsequent code, until the end of the scope where the the import
function was used. A free variable is searched for first in the current module, then its parents as before. If it remains unbound, all imported modules are searched for a binding. The import
function has no effect on unqualified definitions, which are always done against the current module.
I’m still on the fence as to whether modules must explicitly export their symbols so only exported symbols are visible to anything outside the module. This may serve to hide symbols that should be private to the module.
The module system may be implemented, with the exception of the ssyntax for module qualifiers, without hacking into the Arc core itself, I think, and may be doable using only macros, although it is likely to produce a performance hit.
This is a work in progress of course, and I’d like to hear what ideas the Arc community has for a standard module system for the language.