Thread overview
Getting module of a class
Oct 17, 2008
Bill Baxter
Oct 17, 2008
Don
Oct 17, 2008
Bill Baxter
Oct 18, 2008
Don Clugston
Oct 17, 2008
bearophile
Oct 17, 2008
Bill Baxter
Oct 18, 2008
Sergey Gromov
Oct 18, 2008
Sergey Gromov
Oct 18, 2008
KennyTM~
October 17, 2008
I find myself sometimes wanting to get an alias to the module namespace that a given type came from.

The reason is this:  these days it's en vogue to make classes contain as few functions as necessary, and to write everything else as non-member functions.  The problem is that when you are using BigCoreDataStructure a lot in your program it's natural to import that from other modules and in the end you can lose sight of which module BigCoreDataStructure came from (it could be aliased to something else like "BCDS" in your current namespace for instance.)

But now you have a problem because you have access to BCDS but you also want to get at his auxillary non-member functions.    But those didn't get imported because they would gum up the namespace.

I'm thinking it would be nice if you could do something like ModuleOf(BCDS).ANonMemberFuncton to get at one of those non-member functions in BCDS's module whatever that may be.

I think types do have the information of which module they originated in, so technically it should be possible.  Has anyone written a routine that can do this?

--bb
October 17, 2008
Bill Baxter wrote:
> I find myself sometimes wanting to get an alias to the module
> namespace that a given type came from.
> 
> The reason is this:  these days it's en vogue to make classes contain
> as few functions as necessary, and to write everything else as
> non-member functions.  The problem is that when you are using
> BigCoreDataStructure a lot in your program it's natural to import that
> from other modules and in the end you can lose sight of which module
> BigCoreDataStructure came from (it could be aliased to something else
> like "BCDS" in your current namespace for instance.)
> 
> But now you have a problem because you have access to BCDS but you
> also want to get at his auxillary non-member functions.    But those
> didn't get imported because they would gum up the namespace.
> 
> I'm thinking it would be nice if you could do something like
> ModuleOf(BCDS).ANonMemberFuncton to get at one of those non-member
> functions in BCDS's module whatever that may be.
> 
> I think types do have the information of which module they originated
> in, so technically it should be possible.  Has anyone written a
> routine that can do this?
> 
> --bb

Yes. It's in my meta.NameOf module. Which hasn't been updated in quite some time...
October 17, 2008
Bill Baxter:
> I'm thinking it would be nice if you could do something like ModuleOf(BCDS).ANonMemberFuncton to get at one of those non-member functions in BCDS's module whatever that may be.

The standard and simple solution to this problem is to import just the name of the module. You can do this with a static import, and you can use an alias to shorten the module name too:

static import bc = packagename.modulename;
auto x = new bc.SomeClass(...);
...
auto y = bc.nonMemberFunction(...);

Bye,
bearophile
October 17, 2008
On Fri, Oct 17, 2008 at 10:45 PM, bearophile <bearophileHUGS@lycos.com> wrote:
> Bill Baxter:
>> I'm thinking it would be nice if you could do something like ModuleOf(BCDS).ANonMemberFuncton to get at one of those non-member functions in BCDS's module whatever that may be.
>
> The standard and simple solution to this problem is to import just the name of the module. You can do this with a static import, and you can use an alias to shorten the module name too:
>
> static import bc = packagename.modulename;
> auto x = new bc.SomeClass(...);
> ...
> auto y = bc.nonMemberFunction(...);

The truly simplest solution here is just to ignore Scott Meyer's advice and make nonMemberFunction a static member function.  That way if I have access to SomeClass I will always have easy access to nonMemberFunction, regardless of whatever round-about chain of imports and aliases got me SomeClass.

And that's precisely what I was planning to do here.  Then it dawned on me that Scott Meyer's advice would be a lot easier to follow in D if there were a simple way to just get at the enclosing namespace of a type.

Another solution would be if I could put some kind static "pointer" to the enclosing namespace inside the type.  -- Actually that might work well too ...  I think it should be possible to stick "alias foo.bar.TheModule ThisModule;" inside a class.  Hmmm.

Don's solution is neat, but the fact that it's not built-in would still mean that I'll be in the middle of writing code somewhere and have to stop to add the import for the meta module.  And if I wasn't using yet then I need to back up further and actually download Don's module from somewhere etc...

--bb
October 17, 2008
On Fri, Oct 17, 2008 at 10:18 PM, Don <nospam@nospam.com.au> wrote:
> Bill Baxter wrote:
>>
>> I find myself sometimes wanting to get an alias to the module namespace that a given type came from.
>>
>> The reason is this:  these days it's en vogue to make classes contain as few functions as necessary, and to write everything else as non-member functions.  The problem is that when you are using BigCoreDataStructure a lot in your program it's natural to import that from other modules and in the end you can lose sight of which module BigCoreDataStructure came from (it could be aliased to something else like "BCDS" in your current namespace for instance.)
>>
>> But now you have a problem because you have access to BCDS but you also want to get at his auxillary non-member functions.    But those didn't get imported because they would gum up the namespace.
>>
>> I'm thinking it would be nice if you could do something like ModuleOf(BCDS).ANonMemberFuncton to get at one of those non-member functions in BCDS's module whatever that may be.
>>
>> I think types do have the information of which module they originated in, so technically it should be possible.  Has anyone written a routine that can do this?
>>
>> --bb
>
> Yes. It's in my meta.NameOf module. Which hasn't been updated in quite some time...
>

Neat.  Does always give you the true module of definition? Or does it return the module from which the symbol was most immediately imported?

For instance if we have this situation:

-----OriginalModule.d-----
struct TheThing { ... }

----OtherModule.d-----
import OriginalModule: SneakyAlias = TheThing;

----FinalModule.d-----
import OtherModule : SneakyAlias;

moduleOf(SneakyAlias);  // does this resolve to OriginalModule or OtherModule?
------------------------------


--bb
October 18, 2008
Bill Baxter wrote:
> On Fri, Oct 17, 2008 at 10:18 PM, Don <nospam@nospam.com.au> wrote:
>> Bill Baxter wrote:
>>> I find myself sometimes wanting to get an alias to the module
>>> namespace that a given type came from.
>>>
>>> The reason is this:  these days it's en vogue to make classes contain
>>> as few functions as necessary, and to write everything else as
>>> non-member functions.  The problem is that when you are using
>>> BigCoreDataStructure a lot in your program it's natural to import that
>>> from other modules and in the end you can lose sight of which module
>>> BigCoreDataStructure came from (it could be aliased to something else
>>> like "BCDS" in your current namespace for instance.)
>>>
>>> But now you have a problem because you have access to BCDS but you
>>> also want to get at his auxillary non-member functions.    But those
>>> didn't get imported because they would gum up the namespace.
>>>
>>> I'm thinking it would be nice if you could do something like
>>> ModuleOf(BCDS).ANonMemberFuncton to get at one of those non-member
>>> functions in BCDS's module whatever that may be.
>>>
>>> I think types do have the information of which module they originated
>>> in, so technically it should be possible.  Has anyone written a
>>> routine that can do this?
>>>
>>> --bb
>> Yes. It's in my meta.NameOf module. Which hasn't been updated in quite some
>> time...
>>
> 
> Neat.  Does always give you the true module of definition?
> Or does it return the module from which the symbol was most
> immediately imported?
> 
> For instance if we have this situation:
> 
> -----OriginalModule.d-----
> struct TheThing { ... }
> 
> ----OtherModule.d-----
> import OriginalModule: SneakyAlias = TheThing;
> 
> ----FinalModule.d-----
> import OtherModule : SneakyAlias;
> 
> moduleOf(SneakyAlias);  // does this resolve to OriginalModule or OtherModule?
> ------------------------------

It gives you OriginalModule. Aliases get resolved.
October 18, 2008
Sat, 18 Oct 2008 05:58:50 +0900,
Bill Baxter wrote:
> The truly simplest solution here is just to ignore Scott Meyer's advice and make nonMemberFunction a static member function.  That way if I have access to SomeClass I will always have easy access to nonMemberFunction, regardless of whatever round-about chain of imports and aliases got me SomeClass.

To define a non-member, *non-friend* function in D you must define it in a different module than the module in which your class is defined.  Good- bye encapsulation.  :)
October 18, 2008
Sergey Gromov wrote:
> Sat, 18 Oct 2008 05:58:50 +0900,
> Bill Baxter wrote:
>> The truly simplest solution here is just to ignore Scott Meyer's
>> advice and make nonMemberFunction a static member function.  That way
>> if I have access to SomeClass I will always have easy access to
>> nonMemberFunction, regardless of whatever round-about chain of imports
>> and aliases got me SomeClass.
> 
> To define a non-member, *non-friend* function in D you must define it in a different module than the module in which your class is defined.  Good-
> bye encapsulation.  :)

I agree. I'd also agree that file-level encapsulation does make sense. After all, unless fancy code databases are used, the file is the physical unit of protection and change tracking, and it's here to stay. So I don't find one scheme inferior to the other.

A possible improvement would be to introduce "module" as a protection level:

class A
{
public:
   void fun(); // vale tudo
module:
   void gun(); // what private is now
protected:
   void hun(); // zis and derivees
package:
   void iun(); // package-level
private:
   void jun(); // really, really private. I mean it.
}

I'm not sure how much this improve the state of affairs. I guess it's one of those reddit-ish "Vote up if you want to attract Walter's attention..."


Andrei
October 18, 2008
Sat, 18 Oct 2008 11:52:38 -0500,
Andrei Alexandrescu wrote:
> Sergey Gromov wrote:
> > Sat, 18 Oct 2008 05:58:50 +0900,
> > Bill Baxter wrote:
> >> The truly simplest solution here is just to ignore Scott Meyer's advice and make nonMemberFunction a static member function.  That way if I have access to SomeClass I will always have easy access to nonMemberFunction, regardless of whatever round-about chain of imports and aliases got me SomeClass.
> > 
> > To define a non-member, *non-friend* function in D you must define it in a different module than the module in which your class is defined.  Good- bye encapsulation.  :)
> 
> I agree. I'd also agree that file-level encapsulation does make sense. After all, unless fancy code databases are used, the file is the physical unit of protection and change tracking, and it's here to stay. So I don't find one scheme inferior to the other.

I'm only saying that if you are to follow Meyers' advice then ModuleOf() won't help you because any "convenience functions" will be defined in another module.
October 18, 2008
Andrei Alexandrescu wrote:
> Sergey Gromov wrote:
>> Sat, 18 Oct 2008 05:58:50 +0900,
>> Bill Baxter wrote:
>>> The truly simplest solution here is just to ignore Scott Meyer's
>>> advice and make nonMemberFunction a static member function.  That way
>>> if I have access to SomeClass I will always have easy access to
>>> nonMemberFunction, regardless of whatever round-about chain of imports
>>> and aliases got me SomeClass.
>>
>> To define a non-member, *non-friend* function in D you must define it in a different module than the module in which your class is defined.  Good-
>> bye encapsulation.  :)
> 
> I agree. I'd also agree that file-level encapsulation does make sense. After all, unless fancy code databases are used, the file is the physical unit of protection and change tracking, and it's here to stay. So I don't find one scheme inferior to the other.
> 
> A possible improvement would be to introduce "module" as a protection level:
> 
> class A
> {
> public:
>    void fun(); // vale tudo
> module:
>    void gun(); // what private is now
> protected:
>    void hun(); // zis and derivees
> package:
>    void iun(); // package-level
> private:
>    void jun(); // really, really private. I mean it.
> }
> 
> I'm not sure how much this improve the state of affairs. I guess it's one of those reddit-ish "Vote up if you want to attract Walter's attention..."
> 
> 
> Andrei

... Off-topic a bit, but I'd rather to see “package” to be usable between sub-packages (e.g. somelib.feature1.all.d and somelib.feature2.all.d)