April 06, 2014
On 4/6/2014 12:39 PM, "Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang@gmail.com>" wrote:
> On Saturday, 5 April 2014 at 23:26:30 UTC, Walter Bright wrote:
>> I feel that C++ messed up namespace design because:
>>
>> 1. namespaces are not closed
>> 2. they have no relationship with modules
>
> Namespaces are not as powerful as they could have been, but being able to add
> symbols to an external scope (like classes) is very useful if done right (e.g.
> cross-cutting enhancements, adding members to external classes like
> "saveyourself", "printyourself").

It's seriously wrong to allow such. It makes a larger code base nearly impossible to reliably reason about, leading one to rely on conventions like "don't add stuff to namespaces".

D has closed scopes, and members can be "added" to external classes just fine, using CTFE.
April 06, 2014
On Sunday, 6 April 2014 at 20:17:09 UTC, Walter Bright wrote:
> It's seriously wrong to allow such. It makes a larger code base nearly impossible to reliably reason about, leading one to rely on conventions like "don't add stuff to namespaces".

Depends on how it is done. For BETA, there was a seperate "fragment system" that allowed AST specified extension points. This system was used for both extensions and for encapsulation/API definition. You basically defined "slots" in the syntax three where code could be injected (following the grammar of the slot) and what should be hidden etc. It was simplistic elegance IMO:

http://www.cs.au.dk/~beta/Manuals/latest/beta/fragment.html

The weakness was that they didn't allow for dynamic dispatch (required static resolution), but that was an implementation issue, I think.
April 06, 2014
Btw, cross-cutting programming is indeed meant to cater for programming in the large:

http://en.wikipedia.org/wiki/Aspect-oriented_programming
April 06, 2014
On Sunday, 6 April 2014 at 20:17:09 UTC, Walter Bright wrote:
> D has closed scopes, and members can be "added" to external classes just fine, using CTFE.

You mean UFCS? As in, for example, "front" for arrays? It doesn't work as well as advertised though. The issue is that the added members are only visible if the *called* code knows to import the *caller* code. This breaks as soon as you leave your own internal ecosystem.

//----
import a;

struct S //Some object
{
}

//Extend to make it a range.
bool empty(S);
int front(S);
void popFront(S);

//Try it.
void main()
{
    S s;
    foreach(e; s) //Error: invalid foreach aggregate s
        writeln(s);
    s.array(); //Error: template std.range.take cannot...
    a.foo(s); //Error: no property 'popFront' for type 'S'
}
//----
module a;

void foo(T)(T t)
{
    t.popFront();
}
//----
Well that horribly fails.

Because when calling a template, you are only importing the passed argument, but not his ecosystem with it. The only way in D to "really" extend an existing object, is to wrap it into a new object. And even then, the wrapping is limited, because you can't orthogonally wrap (eg the wrapping linearly stacks, whereas UCFS *could* add two completely independent functionalities). Not to mention issues with code bloat...

C++'s namespaces have their flaws, but they *are* scalable in a way D's modules aren't, thanks to Koenig Lookup.
April 06, 2014
On 4/6/2014 2:00 PM, monarch_dodra wrote:
> On Sunday, 6 April 2014 at 20:17:09 UTC, Walter Bright wrote:
>> D has closed scopes, and members can be "added" to external classes just fine,
>> using CTFE.
>
> You mean UFCS?

Yes, my mistake.


> As in, for example, "front" for arrays? It doesn't work as well
> as advertised though. The issue is that the added members are only visible if
> the *called* code knows to import the *caller* code.

That's a feature of a modular system, not a bug. D does not have a global name space, on purpose.

> This breaks as soon as you
> leave your own internal ecosystem.
>
> //----
> import a;
> 
> struct S //Some object
> {
> }
>
> //Extend to make it a range.
> bool empty(S);
> int front(S);
> void popFront(S);
>
> //Try it.
> void main()
> {
>      S s;
>      foreach(e; s) //Error: invalid foreach aggregate s
>          writeln(s);
>      s.array(); //Error: template std.range.take cannot...
>      a.foo(s); //Error: no property 'popFront' for type 'S'
> }
> //----
> module a;
>
> void foo(T)(T t)
> {
>      t.popFront();
> }
> //----
> Well that horribly fails.

That's based on a misunderstanding of how scoped lookup works in D, and how to use it properly. In the particular instance above, there is simply no reason to not put front() as a member of S, since they are in the same module.


> Because when calling a template, you are only importing the passed argument, but
> not his ecosystem with it. The only way in D to "really" extend an existing
> object, is to wrap it into a new object. And even then, the wrapping is limited,
> because you can't orthogonally wrap (eg the wrapping linearly stacks, whereas
> UCFS *could* add two completely independent functionalities). Not to mention
> issues with code bloat...

You're right in that if you try to do things the C++ way in D, things won't work out so well. D can do all these things, but they are done in a different way - a way that is much more robust.

The fault in the C++ method of extending namespaces is that two independently developed modules had better not extend the same namespace with the same names. You will not necessarily get a compiler error from violating this - code may just wind up calling the wrong overload. I.e. it does not scale.


> C++'s namespaces have their flaws, but they *are* scalable in a way D's modules
> aren't, thanks to Koenig Lookup.

I've never seen anyone defend Koenig lookup as anything but a hack before :-)
April 07, 2014
On 2014-04-06 19:39:31 +0000, "Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang@gmail.com> said:

> Unfortunately that seems to be years into the future? Although clang has begun implementing something:
> 
> http://clang.llvm.org/docs/Modules.html
> 
> I've got at feeling that if clang gets something working it will become a de-facto standard due to demand.

Modules are already in use on OS X for some system frameworks. It can result in slightly improved compile times. It has been enabled by default for new Xcode projects for some time. With modules enabled, clang interpret #includes as module imports for system frameworks having a module map. It's so transparent you probably won't notice anything has changed.

The only thing that really changes with modules is you don't have access to symbols you don't have imported yourself. D already works like that. I think D can ignore those modules, just like it ignores header files.

-- 
Michel Fortin
michel.fortin@michelf.ca
http://michelf.ca

April 07, 2014
On Sat, 05 Apr 2014 13:47:32 -0700, Walter Bright <newshound2@digitalmars.com> wrote:

> On 4/2/2014 3:07 PM, Walter Bright wrote:
>> One downside of this proposal is that if we ever (perish the thought!) attempted
>> to interface to C++ templates, this design would preclude that.
>
> Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it:
>
>      extern (C++, namespace = A.B) { void foo(); void bar(); }
>      extern (C++, namespace = C) void foo();
>
>      bar();  // works
>      A.B.bar(); // works
>      foo(); // error: ambiguous
>      C.foo();   // works
>
>      alias C.foo foo;
>      foo();  // works, calling C.foo()
>
> I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary.

This seems like a reasonable way to interop with C++ namespace in a D way. I also think that it is something that we should do ASAP. I know that for Aurora, I will not be able to add complete DirectX support until the C++ namespace interop problem is solved. Specifically because the highly optimized DirectXMath functions are inside a namespace. I do not consider pre-mangling a solution, it's a hack for something that is quite common in C++, and it's fragile.

-- 
Adam Wilson
GitHub/IRC: LightBender
Aurora Project Coordinator
April 07, 2014
On Monday, 7 April 2014 at 01:35:37 UTC, Michel Fortin wrote:
> Modules are already in use on OS X for some system frameworks. It can result in slightly improved compile times. It has been enabled by default for new Xcode projects for some time.

Thanks for sharing, I wasn't aware of that. That means that clang will make this a priority. But I guess clang is a long way from not having end users write their own header files still.
April 07, 2014
On Monday, 7 April 2014 at 08:06:11 UTC, Ola Fosheim Grøstad wrote:
> On Monday, 7 April 2014 at 01:35:37 UTC, Michel Fortin wrote:
>> Modules are already in use on OS X for some system frameworks. It can result in slightly improved compile times. It has been enabled by default for new Xcode projects for some time.
>
> Thanks for sharing, I wasn't aware of that. That means that clang will make this a priority. But I guess clang is a long way from not having end users write their own header files still.

clang developers are the ones driving the ISO C++ Modules working group, so whatever clang does, it will eventually be the standard.

--
Paulo
April 07, 2014
On Saturday, 5 April 2014 at 20:47:29 UTC, Walter Bright wrote:
> On 4/2/2014 3:07 PM, Walter Bright wrote:
>> One downside of this proposal is that if we ever (perish the thought!) attempted
>> to interface to C++ templates, this design would preclude that.
>
> Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it:
>
>     extern (C++, namespace = A.B) { void foo(); void bar(); }
>     extern (C++, namespace = C) void foo();
>
>     bar();  // works
>     A.B.bar(); // works
>     foo(); // error: ambiguous
>     C.foo();   // works
>
>     alias C.foo foo;
>     foo();  // works, calling C.foo()
>
> I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary.

I actually like this idea the most. It is clean, and easy to understand.
1 2 3 4 5 6 7 8 9
Next ›   Last »