[ocaml-platform] on the need and design of OCaml namespaces

Wojciech Meyer wojciech.meyer at gmail.com
Thu Feb 28 14:45:06 GMT 2013


I'd argue that the namespaces in the C++ should be a best example how
to implement namespaces in general.

C++ lacks compilation of interfaces, so the header filles containing
the prototypes, are literaly included. For that reason, in C++ we need
to write something like this:

// Implement pretty printer for complex number class
// but here we want see just Complex class that belongs to the parent namespace
namespace std {
namespace complex {
  class Complex;
  }
}

ostream operator << (const ostream&, const std::complex::Complex&);

for somebody who've never had occasion to use nested namespaces, and
tried, will see how much it is to get the exposed the interface right
which basically originates from the un-natural literal inclusion of
the headers. So the declarations *will* clutter the source files.
Other problem is name mangling, C++ symbols can be very long, and in
case of Clang we get 6GB of RAM to link the compiler. (because of the
templates + literal header inclusion + name mangling). We need to
decide upon how to mangle names.

BTW: I never considered namespaces in C++ as a bad feature of the
language, but when actually I tried use them, I found that maybe there
are quite complex to use in nested setting.

That's said, they are canonnical examples what to do, and what not to
do in the language.

Probably getting it right is not massively difficult as there are just
few possible operations that are sensible on the language level that
implement them and C++ has all of them.
So:

namespace { ... } // Define namespace
using namespace std; // with a local equivalent
using namespace std::complex::Complex // with a local equivalent
new std::complex::Complex; // Fully scoped access
new complex::Complex; // Assuming that the namespace was open before
namespace complex = std::complex; // Alias for a namespace

The same example would apply to OCaml of course.

Sorrry, for these C++ snippets, but I think Erkki in principle was
right that C++ namespaces are very similar to what we want as a basis
of the system, but if I wouldn't say that namespaces in C++ worked
flawlessly in C++ even years ago.


Wojciech

On Thu, Feb 28, 2013 at 9:01 AM, Erkki Seppala
<flux-ocaml-platform at inside.org> wrote:
> TLDR; I agree with the parts of proposal suggesting statement "namespace
> X" to be introduced to .ml and .mli files and then statements "open
> namespace X", "let namespace Y = X" and their expression forms. And that
> this all should be controlled from the source code, not the build
> system.
>
> Yaron Minsky <yminsky at janestreet.com> writes:
>
>>   My biggest objection to having opens be at the build system level is
>>   that it makes your code more ambiguous.  When you do namespace
>>   manipulations, you very much want to see what's happening by
>>   inspecting the source.  We have a vigorous code review system here,
>>   and I don't want to start adding code review of the build rules to
>>   it, and this change would require that.
>
> I agree that namespaces should be defined and accessed through the
> source code. Not the least because it depends on the project's chosen
> build system on how I should go on changing those definitions. While
> currently the situation is the same regarding findlib package
> management, I think it is worth considering that perhaps this kind of
> namespace system could automatically lead into the build system
> (ocamldep?)  inferring which packages you need to use and eliminate that
> piece of configuration from the build system. Only special cases would
> need more configuration.
>
> While C++ might not be the golden standard to look upon on language
> development, perhaps it can serve as an inspiration. Its namespace
> system seems to work pretty nicely without complaints from the
> developers. It has the following constructs:
>
> namespace X {
>   /* introduce values for the namespace X */
>   int a = 42;
>   namespace Z {
>     /* introduce namespace X::Z */
>     int b = a;
>   }
> }
>
> namespace X {
>   /* introduce more values for the namespace X */
>   int z = 5;
> }
>
> namespace Y = X; /* alias a namespace */
>
> int b = X::a; /* access a value in a namespace */
>
> using namespace X; /* bring X to current scope (works in function scope
>                       as well */
>
> using X::a; /* bring one value from a namespace to current scope */
>
> In implementation side it works by simply relabeling symbols in the
> generated object files which makes the namespaces open.
>
> C++'s compilation system with include files is of course very different
> from OCaml, but a similar solution to OCaml would mean having a hidden
> internal name (such as namespace_modulename or possibly even something
> that like namespace#modulename) for the module created from that
> compilation unit. It would need to be limited to a single top-level
> namespace specification per compilation unit, so it would work sort of
> in reverse compared to C++. For example if x.ml contained statement
> "namespace Foo", a module Foo#X would be generated instead of plain X.
>
> This solution would not allow the same module names from different
> namespaces to coexist in a single directory, but I don't see this as an
> essential feature. The source file names already would be the same, and
> OCaml compiler produces object files to the same directory as the
> source. If you have a build system copying files around, it could (and
> perhaps should!) preserve the directory hierarchy.
>
>> - NAMESPACES WITH VALUES.  I have argued for allowing the opening of a
>>   namespace to also implicitly open some modules, this essentially
>
> The previosuly described system would also eliminate the C++-like
> ability of introducing values to a namespace, unless special module
> names or other changes, such as an automatic opening of some modules,
> are implemented. It would be nice to be able to define such top-level
> values from multiple compilation units, but I'm uncertain how that would
> be implemented.
>
> This approach would need the compiler to find many similarly named .cmi
> files and decide the proper one to use based on their contents, as
> mentioned in a previous proposal.
>
> Everyone seems to agree that # is a good operator for accessing modules
> (or values) from namespaces. Or maybe we could go with \ ;-).
>
>>   But what Alain is proposing is to make opening a namespace silent at
>>   the source level.  This strikes me as a grave error.
>
> I agree. At worst this could mean that in large projects developers let
> the build system recompile their files so they can see what namespaces
> they are using. It seems much better to me to just read it from the
> source code, which is the same regardless of the project.
>
> --
>   _____________________________________________________________________
>      / __// /__ ____  __               http://www.modeemi.fi/~flux/\   \
>     / /_ / // // /\ \/ /                                            \  /
>    /_/  /_/ \___/ /_/\_\@modeemi.fi                                  \/
> _______________________________________________
> Platform mailing list
> Platform at lists.ocaml.org
> http://lists.ocaml.org/listinfo/platform


More information about the Platform mailing list