D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 1509 - Need a way to create namespaces inside modules
Summary: Need a way to create namespaces inside modules
Status: RESOLVED WONTFIX
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-09-17 00:49 UTC by Bill Baxter
Modified: 2016-10-14 02:00 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Bill Baxter 2007-09-17 00:49:53 UTC
There's currently no good way to organize a set of functionality under a common namespace within a module.

In C++ one can use the 'namespace' keyword for this.  If you ever look at Boost code, for instance, you'll see they use 'namespace detail' all over the source to group functionality that is an implementation detail.

I'd like to see such a namespace grouping capability added to D.

That's the ehnancement request, now read on for one proposal for how to provide that functionality.

D already has a namespace creation mechanism, namely modules.
For instance, if I want to group some imports or functions together under one namespace called 'detail', in current D I can do that by making a file called 'detail.d' that contains the public imports I want it to have, and any extra functions I want to give it.  Then I 'static import detail;' from mymodule.d, and voila, I have access to all that stuff via 'detail.*'.

This has several drawbacks, however. 
1) it's simply cumbersome to have to make a separate file just to get a new namespace.
2) it is likely that this module will not be imported (and maybe *shouldn't* be imported) by any module besides "mymodule.d".  But that restriction can't be enforced. 
3) For the case of implementation detail modules, 'detail.d' will very likely need access to private members of mymodule.d, which it can't have.  Also vice-versa, mymodule.d may need access to privates of detail.d, which it can't have.
4) You can't realistically just name the module 'detail' because other modules may want to have a namespace called 'detail' too.  So to avoid module naming conflicts it would actually have to be called something unique like "foo.bar.mymodule_detail"

But the module mechanism basically does what is needed, so I don't think it's necessary to add any new keywords, we just need to allow a new use of the 'module' keyword to define an "inner module".

Basic example:

------
module mymodule;
private module Detail {
   import std.stdio;
   import std.string;
   import std.regex;
   void foo() { writefln("I'm an implementation detail"); }
}
...
void public_func() {
   Detail.writefln("hi there");
}
------


Another possibility would be to have "named protection blocks". 

E.g.

private Detail {
  ...
}

public Core {
  ...
}
Comment 1 Bill Baxter 2007-09-17 00:52:42 UTC
Forgot to label this "enhancement".
And maybe V2.0 is more appropriate.
Comment 2 Bill Baxter 2007-09-17 01:05:20 UTC
Here's a workaround from Daniel Keep on the NG:

"""
The way I usually work around this is like so:

template Namespace_()
{
  // Stuff in the namespace.
}

mixin Namespace_ Namespace;

Kinda hacky, but it works  :) 

	-- Daniel
"""

This is certainly better than creating a separate file, but still an awfully bizarre and roundabout way to create a new namespace.
Comment 3 Bill Baxter 2007-09-18 15:05:15 UTC
Walter brought up that a struct with all static methods is also a workaround.

The main functional deficiency with both these workarounds (aside from aesthetic concerns over how kludgy it looks) is that neither solution permits imports into that nested scope.

But allowing imports in nested scopes like structs and functions is another enhancement that would certainly be welcome.
Comment 4 Martin Nowak 2012-02-14 05:17:33 UTC
Importing into functions, templates and structs do work now.
The cleanest way to fake a namespace is to alias a template.

----
cat > test.d << CODE
template MyNameSpace_()
{
  import std.stdio;

  void foo()
  {
      writeln("MyNameSpace.foo");
  }
}
alias MyNameSpace_!() MyNameSpace;

void main()
{
    MyNameSpace.foo();
}
CODE

dmd -run test.d
----
Comment 5 Andrei Alexandrescu 2016-10-14 00:39:47 UTC
I'll close this now, please reopen if necessary.
Comment 6 Bill Baxter 2016-10-14 02:00:47 UTC
Seems like aliased template is a pretty good substitute now. Thanks.