April 28, 2014
On Mon, 28 Apr 2014 10:56:24 -0400, Steven Schveighoffer wrote:

> 
> Most definitely no. When the compiler builds b.d, he has no idea it's imported from inside another namespace! We don't want #include-style issues.
> 
> -Steve

So we would have to include the entire namespace in a single d file or is this okay:

a/package.d
extern(C++, a) {}
public import a.b;

a/b.d
extern(C++, a.b) {}

April 28, 2014
On Mon, 28 Apr 2014 11:05:25 -0400, Byron <byron.heads@gmail.com> wrote:

> On Mon, 28 Apr 2014 10:56:24 -0400, Steven Schveighoffer wrote:
>
>>
>> Most definitely no. When the compiler builds b.d, he has no idea it's
>> imported from inside another namespace! We don't want #include-style
>> issues.
>>
>> -Steve
>
> So we would have to include the entire namespace in a single d file
> or is this okay:
>
> a/package.d
> extern(C++, a) {}
> public import a.b;
>
> a/b.d
> extern(C++, a.b) {}

Yes, that is fine.

You could also nest within the same file. But not via an import. In D, it's important that imports are context-free, it doesn't matter where or when you import them. This eliminates all sorts of problems that #include has.

-Steve
April 28, 2014
On Mon, 28 Apr 2014 10:54:17 -0400, Steven Schveighoffer wrote:

>>>
>>> That doesn't help. foo.func() is still ambiguous. With this proposal, you have hijacked the meaning of namespace lookup. When I say x.y.z, it doesn't just mean look for symbol z in module x/y.d, it can also mean to look for symbol z in C++ namespace x::y. This was not the case with C binding, which continued to use D modules for symbol lookup.
>>>
>>> Consider that a boatload of C++ code is named std::something. Now, std.string has an ambiguous meaning wherever it is used!
>>>
>>> -Steve
>>
>> bar is renamed, thus you have to access via _cpp.[namespace] renames were added to prevent hijacking.
> 
> That renames the bar module, but not the foo C++ namespace, which can be assumed when calling foo.func.
> 
> In reality, you could "fix" the situation by renaming the foo D module, and then foo.func would unambiguously refer to bar's func :)
> 
> Another alternative fix would be to allow renaming C++ namespaces. I strongly recommend against that. The better alternative is to reserve qualified name lookup to D modules alone. Adding a mechanism that is possibly ugly, but that does NOT conflict with module lookup, in order to disambiguate C++ symbols is fine.
> 
> -Steve



I am confused now, cross module renaming??

I was thinking this:

a.d
extern(C++, std) {  ... class string ... }


b.d
import std.string;
import cpp = a; // a must be accessed via cpp

std.string.... /// okay D version
cpp.std.string ... /// okay c++ version
string ... /// Okay D version
cpp.string /// Okay C++ version




April 28, 2014
On Mon, 28 Apr 2014 11:09:38 -0400, Byron <byron.heads@gmail.com> wrote:

> I am confused now, cross module renaming??
>
> I was thinking this:
>
> a.d
> extern(C++, std) {  ... class string ... }

class string now has two fully-qualified names. a.string, and std.string (assuming the current DIP is implemented).

> b.d
> import std.string;
> import cpp = a; // a must be accessed via cpp

This renames the a *module*, but not the C++ namespace. The C++ namespace is entirely separate from D's module imports.

So now, a's string has two names, cpp.string and std.string (still).

> std.string.... /// okay D version

Error. Refers both to the std.string module, and the string class within the std C++ namespace.

> cpp.std.string ... /// okay c++ version

I don't think this would work either. This is a mix of D modules, and C++ namespaces. The DIP does not mention this possibility.

> string ... /// Okay D version

I think this may work.

> cpp.string /// Okay C++ version

Yes.

-Steve
April 28, 2014
On Mon, 28 Apr 2014 11:21:52 -0400, Steven Schveighoffer wrote:

> On Mon, 28 Apr 2014 11:09:38 -0400, Byron <byron.heads@gmail.com> wrote:
> 
>> I am confused now, cross module renaming??
>>
>> I was thinking this:
>>
>> a.d extern(C++, std) {  ... class string ... }
> 
> class string now has two fully-qualified names. a.string, and std.string (assuming the current DIP is implemented).
> 
>> b.d import std.string;
>> import cpp = a; // a must be accessed via cpp
> 
> This renames the a *module*, but not the C++ namespace. The C++ namespace is entirely separate from D's module imports.
> 
> So now, a's string has two names, cpp.string and std.string (still).
> 
>> std.string.... /// okay D version
> 
> Error. Refers both to the std.string module, and the string class within the std C++ namespace.
> 
>> cpp.std.string ... /// okay c++ version
> 
> I don't think this would work either. This is a mix of D modules, and
> C++
> namespaces. The DIP does not mention this possibility.
> 
>> string ... /// Okay D version
> 
> I think this may work.
> 
>> cpp.string /// Okay C++ version
> 
> Yes.
> 
> -Steve



Awesome this help me understand your point.  So why does the namespace live outside of the module? They have to live in the imported scope?  This seems like a big problem to me.  Or I am missing something else?

-Byron
April 28, 2014
On Monday, 28 April 2014 at 14:27:19 UTC, Steven Schveighoffer wrote:
> void main()
> {
>    func(); // error
>    foo.func(); // ALSO error
>    bar.func(); // Not error, BUT it's actually calling foo::func from C++ land!
> }

I don't see any fundamental issue here because you can still use renamed imports to disambiguate any call. However it does feel extremely dirty from the reading clarity point of view and can be a good reason to prohibit naive usage of namespaces in D code in same way as modules.
April 28, 2014
On Mon, 28 Apr 2014 11:32:50 -0400, Dicebot <public@dicebot.lv> wrote:

> On Monday, 28 April 2014 at 14:27:19 UTC, Steven Schveighoffer wrote:
>> void main()
>> {
>>    func(); // error
>>    foo.func(); // ALSO error
>>    bar.func(); // Not error, BUT it's actually calling foo::func from C++ land!
>> }
>
> I don't see any fundamental issue here because you can still use renamed imports to disambiguate any call. However it does feel extremely dirty from the reading clarity point of view and can be a good reason to prohibit naive usage of namespaces in D code in same way as modules.

Yes, but this proposal gets extra negative points for forcing you to rename your D module for the sake of C++ imports :)

For something like std.string, I can't imagine it will be pleasant.

-Steve
April 28, 2014
On Mon, 28 Apr 2014 11:29:53 -0400, Byron <byron.heads@gmail.com> wrote:

> On Mon, 28 Apr 2014 11:21:52 -0400, Steven Schveighoffer wrote:
>
>> On Mon, 28 Apr 2014 11:09:38 -0400, Byron <byron.heads@gmail.com> wrote:
>>
>>> I am confused now, cross module renaming??
>>>
>>> I was thinking this:
>>>
>>> a.d extern(C++, std) {  ... class string ... }
>>
>> class string now has two fully-qualified names. a.string, and std.string
>> (assuming the current DIP is implemented).
>>
>>> b.d import std.string;
>>> import cpp = a; // a must be accessed via cpp
>>
>> This renames the a *module*, but not the C++ namespace. The C++
>> namespace is entirely separate from D's module imports.
>>
>> So now, a's string has two names, cpp.string and std.string (still).
>>
>>> std.string.... /// okay D version
>>
>> Error. Refers both to the std.string module, and the string class within
>> the std C++ namespace.
>>
>>> cpp.std.string ... /// okay c++ version
>>
>> I don't think this would work either. This is a mix of D modules, and
>> C++
>> namespaces. The DIP does not mention this possibility.
>>
>>> string ... /// Okay D version
>>
>> I think this may work.
>>
>>> cpp.string /// Okay C++ version
>>
>> Yes.
>>
>> -Steve
>
>
>
> Awesome this help me understand your point.  So why does the namespace
> live outside of the module? They have to live in the imported scope?

Because C++ has no idea of D modules.

There are two things here, name mangling, and name lookup. The DIP rightly allows proper name mangling, which is difficult to get right (I think even on different platforms the mangling is different), but also overloads name lookup. So you can access a C++ symbol via it's short name (string), it's fully qualified D name (a.string) or it's fully qualified C++ namespace name (std.string).

There is nothing that explains how you could use the module AND the C++ namespace to look up the unambiguous name. But even so, the C++ name conflicts with a D module lookup. And you can only fix it by renaming the D module. I'd rather the DIP not invalidate existing D name lookup, and provide an alternate mechanism to use C++ namespaces for fully qualified symbols.

-Steve
April 28, 2014
On 4/28/2014 12:45 AM, Temtaime wrote:
> I think he meant next:
>
> A.d:
> void foo();
>
> A.cpp:
> namespace A { void foo(); }
>
> And now we has:
>
> exnern(C++, A) void foo();
> import A;

Error, A is defined twice.

April 28, 2014
On 4/28/2014 4:29 AM, "Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang@gmail.com>" wrote:
> This is close. Forgive inaccurate syntax, but I see at least these issues that
> will make namespaces/module-system broken in terms of maintenance:
>
> YEAR 2014:
>
> framework1.d:
> extern (C++, std){ void something(); }
>
> framework2.d:
> extern (C++,std){void something(); void anything();}
>
> application.d:
> import framework1;
> import framework2;
> … std.something(); // is this ok, because the extern signatures match?

No. Even though they are the same function as far as the signatures are concerned, they are different functions as far as the D type system is concerned, and hence the call is ambiguous. You'll have to qualify by framework1.std.something() or framework2.std.something().



> std.d is updated:
> void something(){}
> void coolstuff(){}
>
> application.d is updated to use the new coolstuff():
> import framework1;
> import framework2;
> import.std();
> … std.something(); // namespace encapsulation broken or fail?
> … std.coolstuff();

No problem, std.d overrides because it is imported directly and so std is in the current scope. The current scope overrides imported scopes.


> application.d is corrected to (or using some other resolution):
> import framework1;
> import framework2;
> import.std();
> … framework2.std.something();
> … std.coolstuff();

Again, no problem.


> YEAR 2016:
>
> framework2.d is modified:
> extern (C++,std){ void anything(); }
>
> application.d is recompiled unmodified:
> import framework1;
> import framework2;
> import.std();
>   // fails even though the signature is still in framework1
> … framework2.std.something();

Still no problem. Qualifying it with framework2 says which one you want.

> … std.coolstuff();

Remember std is a symbol in the current scope.


> Right, but I want to be sure that the type-system sees all externs with the same
> signature as the same type.

Remember, a C++ signature is the same as its type in C++, but that is not true of D.


> I also am not sure how the "closing of namespaces"
> will work if you have multiple frameworks that independently specify their own
> C++ bindings to the same library.

D will regard those namespaces as completely separate and distinct scopes. The fact that C++ symbols in those separate scopes will mangle to the same symbol is up to the programmer to deal with - the same as with extern(C) symbols.


> The sole purpose of namespace/modules is to have clean separation between
> frameworks and support evolutionary development. I am not convinced that this
> property is not broken with the proposed change.
>
> To get around this you will have to remove the "closing of namespaces"
> restriction and add a root "cpp" so that all cpp namespaces get:
> cpp.std.something() etc…

I don't think there's anything needed to be gotten around here.