www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Inner modules / namespaces

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
One thing I find I keep wishing D had was a way to make a distinct 
namespace inside a file.  This would make it possible to group bits of 
functionality into namespaces without having to break each one out into 
a separate file.

I think the most natural way to do this would be to allow inner modules. 
  These modules would not be directly importable from outside but would 
be accessible from outside if public.

Basic example:

------
private module Detail {
    import std.stdio;
    import std.string;
    import std.regex;
}
...
Detail.writefln("hi there");
------

This would basically be equivalent to making a separate file called 
"Detail.d" whose contents are

    public import std.stdio;
    public import std.string;
    public import std.regex;

And then doing

    static import Detail;

In the original module.  Except you don't have to actually go through 
the rigmarole of making a separate file.  *ALSO* Detail and the main 
module would have same-module access to each others privates.

The mutual access is the big thing.  You can make separate modules now, 
but that's not so useful for implementing a private "Detail" namespace 
that hides a bunch of non-public functionality behind one name.  Yes, 
you can achieve similar results with a big private {...} block but the 
difference is that you can't give that private block a name.  By putting 
your private stuff in one namespace, it becomes easier for readers of 
the code to figure out what's private functionality and what's not.

The other advantage is that it makes it easier to aggregate several 
modules under a common namespace within a module.  For instance I often 
wish I could do something like

private module Util {
    import std.string;
    import my.utils;
    import your.utils;
}

and get at all those Util things via one Util prefix.  Yes I can do that 
by creating another module with public imports, but I never do, because 
its a pain, and this particular combination of Util modules is probably 
never going to be used anywhere besides this one module.  So it doesn't 
really make sense to create a world-visible module that's basically 
useless aside from inside this one module.

I'm planning to throw this up as an enhancement request on Bugzilla, but 
I thought I'd put it out here first to see what the reaction is.

--bb
Sep 15 2007
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Bill Baxter wrote:
 One thing I find I keep wishing D had was a way to make a distinct 
 namespace inside a file.  This would make it possible to group bits of 
 functionality into namespaces without having to break each one out into 
 a separate file.
 
 I think the most natural way to do this would be to allow inner modules. 
  These modules would not be directly importable from outside but would 
 be accessible from outside if public.
 
 Basic example:
 
 ------
 private module Detail {
    import std.stdio;
    import std.string;
    import std.regex;
 }
 ....
 Detail.writefln("hi there");
 ------
 
 This would basically be equivalent to making a separate file called 
 "Detail.d" whose contents are
 
    public import std.stdio;
    public import std.string;
    public import std.regex;
 
 And then doing
 
    static import Detail;
 
 In the original module.  Except you don't have to actually go through 
 the rigmarole of making a separate file.  *ALSO* Detail and the main 
 module would have same-module access to each others privates.
 
 The mutual access is the big thing.  You can make separate modules now, 
 but that's not so useful for implementing a private "Detail" namespace 
 that hides a bunch of non-public functionality behind one name.  Yes, 
 you can achieve similar results with a big private {...} block but the 
 difference is that you can't give that private block a name.  By putting 
 your private stuff in one namespace, it becomes easier for readers of 
 the code to figure out what's private functionality and what's not.
 
 The other advantage is that it makes it easier to aggregate several 
 modules under a common namespace within a module.  For instance I often 
 wish I could do something like
 
 private module Util {
    import std.string;
    import my.utils;
    import your.utils;
 }
 
 and get at all those Util things via one Util prefix.  Yes I can do that 
 by creating another module with public imports, but I never do, because 
 its a pain, and this particular combination of Util modules is probably 
 never going to be used anywhere besides this one module.  So it doesn't 
 really make sense to create a world-visible module that's basically 
 useless aside from inside this one module.
 
 I'm planning to throw this up as an enhancement request on Bugzilla, but 
 I thought I'd put it out here first to see what the reaction is.
 
 --bb

It would be a nice start (and useful just on itself) if imports were to work on scopes other than the module scope. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 16 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Bruno Medeiros wrote:
 Bill Baxter wrote:
 One thing I find I keep wishing D had was a way to make a distinct 
 namespace inside a file.  This would make it possible to group bits of 
 functionality into namespaces without having to break each one out 
 into a separate file.

 I think the most natural way to do this would be to allow inner 
 modules.  These modules would not be directly importable from outside 
 but would be accessible from outside if public.

 Basic example:

 ------
 private module Detail {
    import std.stdio;
    import std.string;
    import std.regex;
 }
 ....
 Detail.writefln("hi there");
 ------

 This would basically be equivalent to making a separate file called 
 "Detail.d" whose contents are

    public import std.stdio;
    public import std.string;
    public import std.regex;

 And then doing

    static import Detail;

 In the original module.  Except you don't have to actually go through 
 the rigmarole of making a separate file.  *ALSO* Detail and the main 
 module would have same-module access to each others privates.

 The mutual access is the big thing.  You can make separate modules 
 now, but that's not so useful for implementing a private "Detail" 
 namespace that hides a bunch of non-public functionality behind one 
 name.  Yes, you can achieve similar results with a big private {...} 
 block but the difference is that you can't give that private block a 
 name.  By putting your private stuff in one namespace, it becomes 
 easier for readers of the code to figure out what's private 
 functionality and what's not.

 The other advantage is that it makes it easier to aggregate several 
 modules under a common namespace within a module.  For instance I 
 often wish I could do something like

 private module Util {
    import std.string;
    import my.utils;
    import your.utils;
 }

 and get at all those Util things via one Util prefix.  Yes I can do 
 that by creating another module with public imports, but I never do, 
 because its a pain, and this particular combination of Util modules is 
 probably never going to be used anywhere besides this one module.  So 
 it doesn't really make sense to create a world-visible module that's 
 basically useless aside from inside this one module.

 I'm planning to throw this up as an enhancement request on Bugzilla, 
 but I thought I'd put it out here first to see what the reaction is.

 --bb

It would be a nice start (and useful just on itself) if imports were to work on scopes other than the module scope.

You mean like doing 'import std.stdio' inside a function or class? That would be nice, but I think it should be considered separately. That's more in the category of "workarounds for lack of 'using'" whereas this is a workaround for lack of 'namespace'. I don't think we really need a 'namespace' keyword in D because modules already provide basically the same kind of scoping mechanism. The issue is that you can only create such namespaces at the file level. But creating new files just to get new namespaces is inconvenient, and also doesn't fully achieve the same functionality because files also determine access to protected/private members. Well anyway, the overall lack of response to this proposal at least suggests to me that people don't find it overwhelmingly objectionable. So I'll go ahead and file it as an enhancement request. --bb
Sep 16 2007
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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
Sep 16 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Daniel Keep wrote:
 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

Ah, that's a good idea. [Added it to the enh request.] --bb
Sep 16 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Ah, that's a good idea.
 [Added it to the enh request.]

Also, structs inherently create a new namespace. Just declare a struct and make its members static.
Sep 18 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 Ah, that's a good idea.
 [Added it to the enh request.]

Also, structs inherently create a new namespace. Just declare a struct and make its members static.

Yes, well I discarded that one right off the bat. Defining objects never meant to be instantiated just seems silly. Somehow the template trick seems slightly less kludgy. --bb
Sep 18 2007
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Bill Baxter wrote:

 Walter Bright wrote:
 Bill Baxter wrote:
 Ah, that's a good idea.
 [Added it to the enh request.]

Also, structs inherently create a new namespace. Just declare a struct and make its members static.

Yes, well I discarded that one right off the bat. Defining objects never meant to be instantiated just seems silly. Somehow the template trick seems slightly less kludgy. --bb

I find the other solution to be the most kludgy :) Matter of taste as always. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Sep 18 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Lars Ivar Igesund wrote:
 Bill Baxter wrote:
 
 Walter Bright wrote:
 Bill Baxter wrote:
 Ah, that's a good idea.
 [Added it to the enh request.]

and make its members static.

never meant to be instantiated just seems silly. Somehow the template trick seems slightly less kludgy. --bb

I find the other solution to be the most kludgy :) Matter of taste as always.

At least we seem to be in agreement that both solutions register on the kludge-o-meter. :-) --bb
Sep 18 2007
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Bill Baxter wrote:
 Bruno Medeiros wrote:
 Bill Baxter wrote:
 One thing I find I keep wishing D had was a way to make a distinct 
 namespace inside a file.  This would make it possible to group bits 
 of functionality into namespaces without having to break each one out 
 into a separate file.

 I think the most natural way to do this would be to allow inner 
 modules.  These modules would not be directly importable from outside 
 but would be accessible from outside if public.

 Basic example:

 ------
 private module Detail {
    import std.stdio;
    import std.string;
    import std.regex;
 }
 ....
 Detail.writefln("hi there");
 ------

 This would basically be equivalent to making a separate file called 
 "Detail.d" whose contents are

    public import std.stdio;
    public import std.string;
    public import std.regex;

 And then doing

    static import Detail;

 In the original module.  Except you don't have to actually go through 
 the rigmarole of making a separate file.  *ALSO* Detail and the main 
 module would have same-module access to each others privates.

 The mutual access is the big thing.  You can make separate modules 
 now, but that's not so useful for implementing a private "Detail" 
 namespace that hides a bunch of non-public functionality behind one 
 name.  Yes, you can achieve similar results with a big private {...} 
 block but the difference is that you can't give that private block a 
 name.  By putting your private stuff in one namespace, it becomes 
 easier for readers of the code to figure out what's private 
 functionality and what's not.

 The other advantage is that it makes it easier to aggregate several 
 modules under a common namespace within a module.  For instance I 
 often wish I could do something like

 private module Util {
    import std.string;
    import my.utils;
    import your.utils;
 }

 and get at all those Util things via one Util prefix.  Yes I can do 
 that by creating another module with public imports, but I never do, 
 because its a pain, and this particular combination of Util modules 
 is probably never going to be used anywhere besides this one module.  
 So it doesn't really make sense to create a world-visible module 
 that's basically useless aside from inside this one module.

 I'm planning to throw this up as an enhancement request on Bugzilla, 
 but I thought I'd put it out here first to see what the reaction is.

 --bb

It would be a nice start (and useful just on itself) if imports were to work on scopes other than the module scope.

You mean like doing 'import std.stdio' inside a function or class? That would be nice, but I think it should be considered separately. That's more in the category of "workarounds for lack of 'using'" whereas this is a workaround for lack of 'namespace'.

Yeah, it's pretty much a separate issue. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 17 2007