[ocaml-platform] An alternative proposal for namespaces

Alain Frisch alain.frisch at lexifi.com
Wed Mar 20 09:33:44 GMT 2013


Dear all,

I'd like to propose a variant of Leo's proposal ( 
http://www.lpw25.net/2013/03/10/ocaml-namespaces.html ).


1. Getting rid of "simple namespace through filenames"

Leo proposes that a file foo-bar.ml automatically creates a module Bar 
in namespace Foo.  With this approach, collecting all modules available 
in the namespace Foo requires to look for all foo-*.cmi files in the 
search path.  This is known to create problems with dependency analysis 
and generated files.  Moreover, since it is also suggested that the 
source file can be named differently from the target .cmi files, it is 
even more difficult for ocamldep to produce a good result.   Another 
problem which I raised in a previous mail is that loading the whole 
directory might prevent different kind of build systems based which 
infer dependencies by capturing system calls.

I propose to keep search path files as the only way to define 
namespaces.  For the typical user (who relies on ocamlfind), this does 
not change anything.  The overhead for library developers is minimal. 
And this could drastically improve the quality of ocamldep.  It would 
work as follow:

  - A namespace-qualified module name is looked up in search path files 
passed to ocamldep.  For those references, ocamldep can produce a 
dependency to concrete files.  This is the best of both worlds: (i) 
contrary to "ocamldep -modules", the build system does not need to 
recreate the lookup logic (in Leo's proposal, this even requires calling 
ocamldep many times in this process, which might be quite slow);  (ii) 
contrary to "ocamldep" (without -modules), this work well even with 
files to be generated (and even when the source file is named differently).

  - An unqualified module name is resolved by taking local module 
declarations and "open namespace" statement into account.  If the name 
can potentially refer to a namespaced module defined in on the search 
path files passed to ocamldep, ocamldep returns a dependency to concrete 
files as in the case above.  Otherwise, it behaves as of today 
(returning either module names in "-modules" mode or concrete files 
otherwise, by looking at the file system).  Since only non-namespaced 
module names are potentially returned as module names, the build system 
can behave as today (simply looking buildable files in -I directories).


Also, "open namespace Foo" would fail if there is no definition of 
modules under namespace "Foo" in the search path files passed to the 
compiler.  This is more robust than looking for foo-*.cmi files on the 
file system: these files might not exist yet, either because (i) 
dependency analysis is bogus or (ii) there is no actual dependency to 
any module in Foo in the current unit; or, on the contrary, there could 
be foo-*.cmi left from a previous compilation even though we have 
decided e.g. to change the name of the namespace.  It's much better, in 
my opinion, to be able to work with a "closed world" assumption w.r.t. 
namespaces while compiling a single unit.


2. Simplifying search path files

I propose to get:

   (i) rid of aliases;

   (ii) define as an error the situation where the same 
namespace-qualified name is defined twice (with different target files) 
in the set of all search path files used together.

(ii) will strongly encourage libraries to avoid stepping on each other 
feet and thus make the life of the user better.  Conflicts resolved by, 
say, a first-match policy are likely to fail at some point anyway (with 
bad error messages).  Namespaces are introduced to avoid such problems.

Complex namespace manipulation, which could benefit from aliases, are 
likely to be useful only to advanced users.  I don't see it as a 
problem that they have to resolve aliases manually or with very simple 
tools.

A nice consequence is that the ordering of search path files does not 
matter for the resolution of namespaced names to filenames, so the 
findlib package descriptions don't have to deal with it.  Also search 
path files and -I directories become independent concepts (-I 
directories are only used to resolve non-namespaced names).


3. Using search path files for reverse lookup

The information contained in search path files allows the compiler to 
map back from "compilation unit names" to namespaced names.  This 
information can be used by the compiler the produce nicer error messages 
involving namespaced names.  (This might be implicit in Leo's proposal.) 
   Here, we can define a first-match policy for this reverse lookup (if 
the same compilation unit is given several namespaced names).

The same applies for ocamldoc.


4. Replacing "-name"

Leo proposes to allow specifying the target compilation unit name 
(*.cmi/*.cmo/*.cmx/*.o) with a new compiler command-line argument.

The use case is to simplify the life of library developers so that they 
don't need to use long names for all their source files.  This should 
greatly simplify the migration of existing libraries to namespaces.
In practice, however, most the source files in such a library will need 
to include a new "open namespace" directive to make other modules from 
the same library accessible.  Also, we will need to inform the build 
system about the relation between source and target filenames.  For 
ocamlbuild, for instance, this will probably mean the creation of a new 
kind of text file to describe this mapping.

Since libraries will need to ship search path files anyway, I think we 
can reuse them to simplify further the migration to namespaces.  I 
propose to support calling the compiler with a "-namespace" argument:

   ocamlc -c mylib.mlpath -namespace Mylib bar.mli

This will do three things:

  - Lookup in mylib.mlpath for the compilation unit name corresponding 
to Mylib..Bar and use it as the target filename (if mylib.mlpath 
contains a line "Mylib..Bar:mylib_xxx", then the compiler will compile 
bar.mli to mylib_xxx.cmi).  We hard-code in particular that in this 
mode, the source filename is equal to the module name as seen by 
"clients" of the library.

  - Automatically "open namespace Mylib" for compiling bar.mli

  - Keep a reference to the "-namespace" argument in the generated .cmi 
file.

Tools could then benefit from the fact that the source file (bar.ml) can 
be retrieved mechanically from either the compilation unit name 
(mylib_xxx) or the qualified name (Mylib..Bar).  And ocamlbuild and 
other build systems don't need to introduce another way to map form 
source file names to compilation unit names.



-- Alain


More information about the Platform mailing list