From: Keith H Duggar on
On Jul 30, 10:23� pm, Walter Bright <newshou...(a)digitalmars.com>
wrote:
> Keith H Duggar wrote:
> > On Jul 29, 9:15 am, Walter Bright <newshou...(a)digitalmars.com> wrote:
> >> Why do namespaces fail to resolve this issue (aside from the
> >> preprocessor)?
>
> > For one there is a need for automatically generating unique
> > easy to use one-off names for helper/detail functions etc.
> > Currently anonymous namespaces do this per translation unit.
> > So I can without fear use short generic names for helpers
> > etc for example:
>
> > a.cpp
> > namespace {
> > void dump ( ) { ... }
> > }
>
> > b.cpp
> > namespace {
> > void dump ( ) { ... }
> > }
>
> > if both a.cpp and b.cpp are included at the bottom on the
> > .hpp file then when that .hpp is eventually included in some
> > .cpp translation unit there will be name clashes.
>
> > The problem turns from annoying to dangerous when there are
> > overloaded helper/detail functions because then instead of
> > getting ambiguity errors your code just silently changes.
>
> Thanks, that's pretty much what I thought. The problem is that
> C++ namespaces are not closed, in that later on the namespace's
> name space can be added to. I feel this is a serious error in
> the design of namespaces, but fixing that would be enormously
> easier than implementing exported templates.
>
> (After all, one cannot add to a function, struct, enum, etc.,
> after its closing brace.)

Judging from my own experience and looking at "professional"
libraries such as STL, Boost, and many others, it seems that
open namespaces are very useful. Perhaps instead of throwing
them out we just need a way to optionally create closed ones.
Given the C++ aversion to new keywords maybe something like:

namespace Foo [ ]
namespace Foo ! { }
namespace Foo = { }

;-)

However, open/close is not the only problem demonstrated by
my example. In fact the primary problem that I see is how to
enable support for short partially qualified names without
clashes? A C++ translation unit provides lexical isolation
making this possible:

a.cpp ;
namespace {
void dump ( ) { ... }
}

void aFoo ( ) { ... dump() ... }

b.cpp ;
namespace {
void dump ( ) { ... }
}

void bFoo ( ) { ... dump() ... }

How do we achieve the same convenience without such lexical
barriers as that imposed implicity by a translation unit?
In other words I don't want to have to write this:

a.hpp : (cause it's in one "java like" file now)
namespace a_detail {
void dump ( ) { ... }
}

void aFoo ( ) { ... a_detail::dump() ... }

Note also the translation unit provides lexical isolation
without nesting aFoo into an additional namespace layer. Ie
I don't want to be forced into this either:

a.hpp : (cause it's in one "java like" file now)

namespace a_detail {
namespace {
void dump ( ) { ... }
}

void aFoo ( ) { ... dump() ... }
}

using a_detail::aFoo ;

> > And, no, forcing users to generate their own unique names for
> > helper namespaces (ala private_someunique) and requiring them
> > to prefix throughout and/or telling them they should just nest
> > everything into their already unique class name (ala Java) are
> > not acceptable "solutions".
>
> In a sensible implementation of imports, the modules being
> imported must each exist in their own, closed, name spaces.
> So, one way or another, you'll need to name each source
> module with a unique name.

Is the D module and import system close to your view of ideal?
What, if anything, would you change about it?

KHD


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Timothy Madden on
Walter Bright wrote:
> Timothy Madden wrote:
>> Walter Bright wrote:
[...]
>
> I am not on the Committee and do not speak for it, but given the history of
> export, I expect that the members will not give the time of day to someone
> simply arguing for export. A practical implementation demonstrating it's
> a good
> idea would be the only thing that'll get an audience. Keep in mind that
> the only
> existing implementation failed to prove it's a good idea.

Yeah I was afraid of that ... :(

Anyway I find that the existing implementation did not go for the whole
thing, as it still requires sources for the template instantiation, and
that compiles an entire .cpp file, not just the pre-parsed template
source. I hear they also do this recursively ?? So yes, the existing
implementation is not a very good example of export... I still wonder
why they considered the symbol tables too large and went for this approach.

The point is however that to keep export the committee would need to see
it implemented and useful, and to have it implemented I would like it
kept in the language :) If only I were in high school again and have as
much time as in a summer holiday.

Thank you,
Timothy Madden

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Walter Bright on
Keith H Duggar wrote:
> On Jul 30, 10:23� pm, Walter Bright <newshou...(a)digitalmars.com>
> wrote:
>> Thanks, that's pretty much what I thought. The problem is that
>> C++ namespaces are not closed, in that later on the namespace's
>> name space can be added to. I feel this is a serious error in
>> the design of namespaces, but fixing that would be enormously
>> easier than implementing exported templates.
> Judging from my own experience and looking at "professional"
> libraries such as STL, Boost, and many others, it seems that
> open namespaces are very useful.

Yes, they are seductively useful. There were a lot of proposals for changes in
the D module system that would have required being able to inject more names
into an existing name space. We killed those proposals with prejudice.

Injecting names into a scope violates about every principle of encapsulation
I've ever heard of. It makes for code that has uncontrollable behavior, in that
in order to understand what it does, you have to look at the *whole project*
rather than just that module. It means your carefully constructed module can be
sabotaged by unrelated modules.

A key element to successful module design is making the meaning of the symbols
in it *independent* of the context that imports it.

The C++ model of #include, extending namespaces, ADL, friends, make for poor
control over encapsulation and modularity. This may not be fixable, as (as you
say) so much code has come to rely on it.

(Note I am using the terms module, import, and namespace rather interchangeably
here.)


> However, open/close is not the only problem demonstrated by
> my example. In fact the primary problem that I see is how to
> enable support for short partially qualified names without
> clashes?

That's an excellent question. In D, the degenerate case where the name is unique
among all the modules in scope is the obvious, trivial case. When the names are
not unique, and the overloading is disjoint, it also works. If the overloads are
not disjoint, there is an ambiguity error and qualifying the names becomes
necessary.

There's much more detail on how this works here:
http://www.digitalmars.com/d/2.0/hijack.html

The anti-hijacking design is, as far as I know, unique to D and has been very
successful.


> Is the D module and import system close to your view of ideal?

I'm very satisfied with it.

> What, if anything, would you change about it?

The order that a module's static constructor runs is controlled by the graph of
how modules import other modules, in a depth-first manner. Trying to figure out
the right thing to do when the graph contains cycles is problematic, though.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Walter Bright on
Timothy Madden wrote:
> If you want instantiation on two subsets of object files at the same
> time you get to the locking problem ... :)

I meant by global database that it's global to the project, rather than global
for your network. Hence, there is no locking problem.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Seungbeom Kim on
On 2010-08-01 22:53, Walter Bright wrote:
>
> Injecting names into a scope violates about every principle of encapsulation
> I've ever heard of. It makes for code that has uncontrollable behavior, in that
> in order to understand what it does, you have to look at the *whole project*
> rather than just that module. It means your carefully constructed module can be
> sabotaged by unrelated modules.

I have never thought of namespaces as a real encapsulation mechanism,
even though they may be closely related to one, such as modules. They
are solutions to the common problem of having to prefix names to avoid
name clashes. They don't provide any access control, nor do they provide
abstraction in place of hidden details, either. For what needs to be
hidden or protected from outside, you have classes with private parts.

"Namespaces is a mechanism for expressing logical grouping."
- Bjarne Stroustrup, TC++PL sp.ed.

I think they are good for what they are designed for.

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]