[ocaml-platform] on the need and design of OCaml namespaces
Török Edwin
edwin+ml-ocaml at etorok.net
Wed Feb 27 17:24:12 GMT 2013
On 02/27/2013 06:31 PM, Yaron Minsky wrote:
> Let me try to summarize the current situation about the argument
> between Alain, Leo and myself. I think Leo and I are roughly on the
> same page, but I may be missing things.
>
> - MAKING LONG NAMES AVAILABLE. Alain prefers to have unambiguous long
> names that are usable in a first class way. I find this mildly
> distasteful, but would be OK with it as long as it was well hidden
> from the user by default. Long names shouldn't show up by default
> in source files, error messages or documentation. I view this as
> quite important for usability of namespaces.
>
> - SOURCE-LEVEL OPENS. Alain would prefer to have namespace
> manipulations restricted to the command line, and therefore the
> build system. He thinks of namespaces as something that should be
> used pretty rarely (or at least, there should be very few
> namespaces), and it's therefore OK to push them to the outside.
>
> Leo and I both believe this is a big mistake. We expect opens to
> happen fairly commonly, and for there to be many different libraries
> that are organized as namespaces.
>
> Alain doubts that there would be many module-name clashes. I
> disagree on this point as does Leo. We use packed modules
> pervasively (for /every/ library), and as a result, we have lots of
> little namespaces, and lots of repeated names within them (names
> like Common, Protocol, Spec, Config, etc.)
>
> 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.
>
> Alain's claim that opens are a bad thing also seems wrong to me.
> opens should be rare, but all of our proposals involve the
> equivalent of opening a namespace. Alain is not saying we should
> have none of that (after all, we're all glad that Pervasives is
> opened!). But what Alain is proposing is to make opening a
> namespace silent at the source level. This strikes me as a grave
> error.
>
> - NAMESPACES WITH VALUES. I have argued for allowing the opening of a
> namespace to also implicitly open some modules, this essentially
> adding values to the search path in addition to modules. I would be
> sad to lose this feature, but I don't think it's absolutely
> essential. It would merely add boilerplate. Roughly speaking,
> every time a user of Core writes
>
> open namespace Core#Std
>
> instead of
>
> open namespace Core#Std
> open Core#Std.Common
>
> they're making a mistake. I'd like to avoid this error, and I don't
> know really what the objection to the feature is, but in the worst
> case, we can add a syntax extension to work around this problem,
> using a -ppx transformer to add the open ourselves.
I'd like to add a suggestion for the last last two requirements, from an OCaml user's perspective (i.e. not a platform/platform library implementor).
I don't feel too strongly about what the exact syntax or build system requirements are for namespaces, its just a suggestion.
core/std/common.mli:
namespace Core#Std
(* define a module Common in the Core#Std namespace.
* Effect: rename module to Core#Std.Common in the .cmi *)
....
core/std/common.ml:
namespace Core#Std
(* define a module Common in the Core#Std namespace.
* Effect: rename module to Core#Std.Common in the .cmi *)
....
Optionally one could also specify -root <path> on the cmdline to automatically create a namespace based on directory hierarchy.
If both are specified its checked that they are equal, and if not an error is shown.
core.mli:
namespace Std = struct
module Core#Std.Common (* defines that this module is part of the namespace *)
module Core#SomethingElse.SomeOtherModule
open Core#Std.Common
(* defines the Core#Std namespace in the .cmi, and the list of default opens to Core#Std.Common *)
(* each namespace must have a .cmi named after its toplevel name
end
file_using_core.ml:
open Core#Std (* this opens the Core#Std namespace, and the Core#Std.Common module *)
(* Core#Std is of type 'namespace', so the compiler would know you open a namespace without having to explicitly say so with a keyword *)
(* you could even write *)
open Core (* opens Core namespace *)
open Std.Common (* opens Core#Std.Common module *)
namespace aliasing, and toplevel use:
> namespace Foo = Core#Std
namespace Foo = <
module Core#Std.Common: sig .... end
module Core#Std.SomeModule: sig .... end
... all modules ...
open Core#Std.Common
How to find the module Foo#Bar.M:
when searching for .cmi files:
look for foo.cmi, and check namespace definitions inside
when searching for .cmx/.cmo files (this is not optimal!):
look for m.cmx/m.cmo, and check that full module name is good, skip to next in search path if not
when searching for .cmxa/.cma files:
look for a foo.cmxa/foo.cma -> defines all modules for namespace Foo.
At link time only the modules that are actually used are kept (since opening a namespace doesn't have side-effects, unused namespaces/modules can be thrown away).
Best regards,
--Edwin
More information about the Platform
mailing list