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

Gabriel Scherer gabriel.scherer at gmail.com
Thu Feb 28 15:07:09 GMT 2013


> 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

Note that all these operations are expressible from the primitives
considered in the specification
http://gallium.inria.fr/~scherer/namespaces/spec.pdf :
- "namespace { ... }" is just a compilation environment literal
- "using namespace std" is a transformation that turns the compilation
environment Env into (Env + Env#Std), where "+" is some choice of
merge operator among those described in the specification (the
differences are in how conflicts are handled and subenvironments are
treated)
- rebinding similarly turns Env into (Env + { Complex => Env#Std#Complex })

On Thu, Feb 28, 2013 at 3:45 PM, Wojciech Meyer
<wojciech.meyer at gmail.com> wrote:
> 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
> _______________________________________________
> Platform mailing list
> Platform at lists.ocaml.org
> http://lists.ocaml.org/listinfo/platform


More information about the Platform mailing list