August 24, 2007
Bill Baxter wrote:
> Walter Bright wrote:
>> Bill Baxter wrote:
>>> Walter Bright wrote:
>>>> C++0x's new features are essentially all present in D 1.0.
>>>
>>> ..but C++98's features that were missing from D are still missing (both good and bad ones).
>>
>> Like what? Virtual base classes? Argument dependent lookup? #include files? C++ can keep them <g>.
> 
> The things that have me banging my head most often are
> 1) the few things preventing an implementation of smart pointers [destructors, copy constructors and opDot].  There are some cases where you just want to refcount objects.  This is the one hole in D that I haven't heard any reasonable workaround for.  I don't necessarily _want_ copy constructors in general but they seem to be necessary for implementing automatic reference counting.

Sorry for the self-follow-up, but I just wanted to add that really C++ smart pointers are themselves kind of klunky due to the fact that _all_ you have access to is that operator*/operator-> thing.  So for instance if you make a boost::shared_ptr<std::map>, you end up always having to dereference to do anything interesting involving operator overloads. mymap["foo"] doesn't work, you need to use (*mymap)["foo"]. What you really want most of the time is something more like "smart references".

This kind of thing is coming close to possibility with the reflection stuff some people are doing.  Basically shapred_ptr!(T) would do introspection on T and populate itself with basic foward-to-T implementations of all of T's methods.

But that seems kind of heavyweight to me.  All you really want to do is define a fallback -- when the compiler sees foo[x] and foo is a shared_ptr!(T), there should be a way to tell it to check T for an opIndex if the shared_ptr itself doesn't have one.

That would handle the access syntax.  But that still leaves the destructor/copy constructors necessary to get a real smart pointer.

> 2) lack of a way to return a reference.

This would also be less critical given a way to fall-back to a member's implementation.

> 3) From what I can tell "const ref" doesn't work for parameters in D 2.0. Oh, and
> 4) real struct constructors.  Just a syntactic annoyance, but still an annoyance.

--bb
August 24, 2007
Bill Baxter wrote:
> The things that have me banging my head most often are
> 1) the few things preventing an implementation of smart pointers [destructors, copy constructors and opDot].  There are some cases where you just want to refcount objects.  This is the one hole in D that I haven't heard any reasonable workaround for.  I don't necessarily _want_ copy constructors in general but they seem to be necessary for implementing automatic reference counting.
> 2) lack of a way to return a reference.
> 3) From what I can tell "const ref" doesn't work for parameters in D 2.0. Oh, and
> 4) real struct constructors.  Just a syntactic annoyance, but still an annoyance.

These will all be addressed in 2.0.
August 24, 2007
Reiner Pope wrote:
>  1. Will specialisation be "fixed" to work with IFTI?

You can simply specialize the parameter to the function.

>  2. Will there be a way to support user-defined specialisations, for instance once which don't depend on the inheritance hierarchy?

I don't know what that means - interfaces are already user-defined.
August 24, 2007
Walter Bright wrote:
> Reiner Pope wrote:
>>  1. Will specialisation be "fixed" to work with IFTI?
> 
> You can simply specialize the parameter to the function.

I'm not sure what you mean. But what I refer to is the part of the spec (the templates page, under Function Templates) that says

"Function template type parameters that are to be implicitly deduced may not have specializations:"

and gives the example:

void Foo(T : T*)(T t) { ... }

int x,y;
Foo!(int*)(x);   // ok, T is not deduced from function argument
Foo(&y);         // error, T has specialization


Perhaps you mean that you can write

void Foo(T)(T* t) { ... }
...
int x;
Foo(&x);

Sure. But the following doesn't work:

void Foo(T)(T t) { ... }
void Foo(T)(T* t) { /* different implementation for this specialisation  */ }
...
int x;
Foo(x);
Foo(&x); // ambiguous

and using template parameter specialisation, IFTI breaks.

> 
>>  2. Will there be a way to support user-defined specialisations, for instance once which don't depend on the inheritance hierarchy?
> 
> I don't know what that means - interfaces are already user-defined.

They are, but they only allow you to stipulate requirements on the types place in the inheritance hierarchy. Two things that inheritance doesn't cover is structural conformance, and complicated predicates.

Structural conformance is clearly important simply because templates make it possible and it avoids the overheads of inheriting from an interface. This is what C++ Concepts have on D interface specialisation.

As to complicated predicates, I refer to the common idiom in D templates which looks like the following:

template Foo(T)
{
    static assert(SomeComplicatedRequirement!(T),
        "T doesn't meet condition");
    ... // implementation

}

(SomeComplicatedRequirement is something inexpressible with the inheritance system; something like "a static array with a size that is a multiple of 1KB")

Some people have suggested (Don Clugston, from memory) that failing the static assert should cause the compiler to try another template overload. I thought this would be easier if you allowed custom specialisations on templates. This would allow the above idiom to turn into something like

template Foo(T :: SomeComplicatedRequirement)
{
    ...
}


(The rest is just how I think it should work)

The user-defined specialisation would be an alias which must define two templates which can answer the two questions:

 - does a given type meet the requirements of this specialisation?
 - is this specialisation a superset or subset of this other specialisation, or can't you tell? (giving the partial ordering rules)

This allows user-defined predicates to fit in neatly with partial ordering of templates.


   -- Reiner
August 24, 2007
Reiner Pope wrote:
> Walter Bright wrote:
>> Reiner Pope wrote:
>>>  1. Will specialisation be "fixed" to work with IFTI?
>>
>> You can simply specialize the parameter to the function.
> 
> I'm not sure what you mean. 

Neither am I...

[snip]

> Sure. But the following doesn't work:
> 
> void Foo(T)(T t) { ... }
> void Foo(T)(T* t) { /* different implementation for this specialisation  */ }
> ...
> int x;
> Foo(x);
> Foo(&x); // ambiguous
> 
> and using template parameter specialisation, IFTI breaks.

This is the workaround I've been using:

void Foo_(T: T*)(T* a) { writefln("ptr"); }
void Foo_(T)(T a) { writefln("non-ptr"); }

// dispatcher
void Foo(T)(T x) { Foo_!(T)(x); }

void main() {
	int x;
	Foo(x);
	Foo(&x);
}

>>>  2. Will there be a way to support user-defined specialisations, for instance once which don't depend on the inheritance hierarchy?
>>
>> I don't know what that means - interfaces are already user-defined.
> 
> They are, but they only allow you to stipulate requirements on the types place in the inheritance hierarchy. Two things that inheritance doesn't cover is structural conformance, and complicated predicates.
> 
> Structural conformance is clearly important simply because templates make it possible and it avoids the overheads of inheriting from an interface. This is what C++ Concepts have on D interface specialisation.
> 
> As to complicated predicates, I refer to the common idiom in D templates which looks like the following:
> 
> template Foo(T)
> {
>     static assert(SomeComplicatedRequirement!(T),
>         "T doesn't meet condition");
>     ... // implementation
> 
> }
> 
> (SomeComplicatedRequirement is something inexpressible with the inheritance system; something like "a static array with a size that is a multiple of 1KB")
> 
> Some people have suggested (Don Clugston, from memory) that failing the static assert should cause the compiler to try another template overload. I thought this would be easier if you allowed custom specialisations on templates. This would allow the above idiom to turn into something like
> 
> template Foo(T :: SomeComplicatedRequirement)
> {
>     ...
> }


> The user-defined specialisation would be an alias which must define two templates which can answer the two questions:
> 
>  - does a given type meet the requirements of this specialisation?
>  - is this specialisation a superset or subset of this other specialisation, or can't you tell? (giving the partial ordering rules)
> 
> This allows user-defined predicates to fit in neatly with partial ordering of templates.

My suggestion has been the following:

template Foo(T : <compile time expression yielding boolean value>), where the expression may depend on T. E.g:

template Foo(T: RandomIndexableContainer!(T)) { ... }

template RandomIndexableContainer(T) {
  const RandomIndexableContainer =
	HasMember!(T, "ValueType") &&
	HasMember!(T, "length") &&
	HasMember!(T, "opIndex",int);
}

Even something like this should be possible:

struct RandomIndexableContainerConcept {...}

template Foo(T: Implements!(T, RandomIndexableContainerConcept)) {
}

or something.

This suggestion lacks the partial ordering of specializations, but those could be probably imposed on a case by case basis by nesting the conditions.


-- 
Oskar
August 24, 2007
Walter Bright wrote:
> Bill Baxter wrote:
>> The things that have me banging my head most often are
>> 1) the few things preventing an implementation of smart pointers [destructors, copy constructors and opDot].  There are some cases where you just want to refcount objects.  This is the one hole in D that I haven't heard any reasonable workaround for.  I don't necessarily _want_ copy constructors in general but they seem to be necessary for implementing automatic reference counting.
>> 2) lack of a way to return a reference.
>> 3) From what I can tell "const ref" doesn't work for parameters in D 2.0. Oh, and
>> 4) real struct constructors.  Just a syntactic annoyance, but still an annoyance.
> 
> These will all be addressed in 2.0.

Hot diggity.  Looking forward to it.

--bb
August 24, 2007
Bill Baxter wrote:
> Bill Baxter wrote:
>> Walter Bright wrote:
>>> Bill Baxter wrote:
>>>> Walter Bright wrote:
>>>>> C++0x's new features are essentially all present in D 1.0.
>>>>
>>>> ..but C++98's features that were missing from D are still missing (both good and bad ones).
>>>
>>> Like what? Virtual base classes? Argument dependent lookup? #include files? C++ can keep them <g>.
>>
>> The things that have me banging my head most often are
>> 1) the few things preventing an implementation of smart pointers [destructors, copy constructors and opDot].  There are some cases where you just want to refcount objects.  This is the one hole in D that I haven't heard any reasonable workaround for.  I don't necessarily _want_ copy constructors in general but they seem to be necessary for implementing automatic reference counting.
> 
> Sorry for the self-follow-up, but I just wanted to add that really C++ smart pointers are themselves kind of klunky due to the fact that _all_ you have access to is that operator*/operator-> thing.  So for instance if you make a boost::shared_ptr<std::map>, you end up always having to dereference to do anything interesting involving operator overloads. mymap["foo"] doesn't work, you need to use (*mymap)["foo"]. What you really want most of the time is something more like "smart references".
> 
> This kind of thing is coming close to possibility with the reflection stuff some people are doing.  Basically shapred_ptr!(T) would do introspection on T and populate itself with basic foward-to-T implementations of all of T's methods.
> 
> But that seems kind of heavyweight to me.  All you really want to do is define a fallback -- when the compiler sees foo[x] and foo is a shared_ptr!(T), there should be a way to tell it to check T for an opIndex if the shared_ptr itself doesn't have one.
> 
> That would handle the access syntax.  But that still leaves the destructor/copy constructors necessary to get a real smart pointer.
> 
>> 2) lack of a way to return a reference.
> 
> This would also be less critical given a way to fall-back to a member's implementation.

Funny, after reading you post I was thinking that you would provide a way to fallback by returning a reference :P

eg.

ref T opDereference()
{
  return ptr;
}

which would then automatically be called when using [] . etc on a T*

I guess we wait and see what Walter cooks up for us in 2.0 :)

Regan
August 24, 2007
Regan Heath wrote:
> Bill Baxter wrote:
>> Bill Baxter wrote:
>>> Walter Bright wrote:
>>>> Bill Baxter wrote:
>>>>> Walter Bright wrote:
>>>>>> C++0x's new features are essentially all present in D 1.0.
>>>>>
>>>>> ..but C++98's features that were missing from D are still missing (both good and bad ones).
>>>>
>>>> Like what? Virtual base classes? Argument dependent lookup? #include files? C++ can keep them <g>.
>>>
>>> The things that have me banging my head most often are
>>> 1) the few things preventing an implementation of smart pointers [destructors, copy constructors and opDot].  There are some cases where you just want to refcount objects.  This is the one hole in D that I haven't heard any reasonable workaround for.  I don't necessarily _want_ copy constructors in general but they seem to be necessary for implementing automatic reference counting.
>>
>> Sorry for the self-follow-up, but I just wanted to add that really C++ smart pointers are themselves kind of klunky due to the fact that _all_ you have access to is that operator*/operator-> thing.  So for instance if you make a boost::shared_ptr<std::map>, you end up always having to dereference to do anything interesting involving operator overloads. mymap["foo"] doesn't work, you need to use (*mymap)["foo"]. What you really want most of the time is something more like "smart references".
>>
>> This kind of thing is coming close to possibility with the reflection stuff some people are doing.  Basically shapred_ptr!(T) would do introspection on T and populate itself with basic foward-to-T implementations of all of T's methods.
>>
>> But that seems kind of heavyweight to me.  All you really want to do is define a fallback -- when the compiler sees foo[x] and foo is a shared_ptr!(T), there should be a way to tell it to check T for an opIndex if the shared_ptr itself doesn't have one.
>>
>> That would handle the access syntax.  But that still leaves the destructor/copy constructors necessary to get a real smart pointer.
>>
>>> 2) lack of a way to return a reference.
>>
>> This would also be less critical given a way to fall-back to a member's implementation.
> 
> Funny, after reading you post I was thinking that you would provide a way to fallback by returning a reference :P
> 
> eg.
> 
> ref T opDereference()
> {
>   return ptr;
> }
> 
> which would then automatically be called when using [] . etc on a T*
> 
> I guess we wait and see what Walter cooks up for us in 2.0 :)

Really I'd rather have something that gives a little more control. Returning a reference is like pulling down your pants in public.

--bb
August 26, 2007
eao197 wrote:
> AFAIK, C++0x doesn't break compatibility with C++98. So if I teach students C++98 now they could use C++0x. Moreover they could use in C++0x all their C++98 code.

It's not a perfect superset, but the breakage is very small.

> Now I see D 2.0 as very different language from D 1.0.

There is more breakage from 1.0 to 2.0, but the changes required are straightforward to find and correct.

>>> To outperform C++ in 2009-2010 D must have full strength now and must be stable during some years to proof that strength in some killer applications.
>>
>> C++0x's new features are essentially all present in D 1.0.
> 
> Yes, but C++ doesn't require programmers to change their language, tools and libraries. Such change require a lot of time and efforts. Such effors could be applied to the current projects instead of switching to D. But, if D could afford something else, something that completely missing from C++0x (like non-null reference/pointers, some kind of functional programming (pattern-matching) and so on) than such switching would be much more attractive.

D 1.0 provides a lot of things completely missing in C++0x:

1) unit tests
2) documentation generation
3) modules
4) string mixins
5) template string & floating point parameters
6) compile time function execution
7) contract programming
8) nested functions
9) inner classes
10) delegates
11) scope statement
12) try-finally statement
13) static if
14) exported templates that are implementable
15) compilation speeds that are an order of magnitude faster
16) unambiguous template syntax
17) easy creation of tools that need to parse D code
18) synchronized functions
19) template metaprogramming that can be done by mortals
20) comprehensive support for array slicing
21) inline assembler
22) no crazy quilt dependent/non-dependent 2 level lookup rules that major compilers still get wrong and for which I still regularly get 'bug' reports because DMC++ does it according to the Standard
23) standard I/O that runs several times faster
24) portable sizes for types
25) guaranteed initialization
26) out function parameters
27) imaginary types
28) forward referencing of declarations

> I know that you work very hard on D, but D 1.0 took almost 7 years. D 2.0 started in 2007, so final D 2.0 could be in 2014?

Even if it does take that long, D 1.0 is still far ahead, and is available now.

To see how much more productive D is, compare Kirk McDonald's amazing PyD http://pyd.dsource.org/dconf2007/presentation.html with Boost Python.

To see what D can do that C++ can't touch, see Don Clugston's incredible optimal code generator at http://s3.amazonaws.com/dconf2007/Don.ppt
August 26, 2007
The first of all -- thanks for your patience!

On Sun, 26 Aug 2007 10:35:47 +0400, Walter Bright <newshound1@digitalmars.com> wrote:

>> Now I see D 2.0 as very different language from D 1.0.
>
> There is more breakage from 1.0 to 2.0, but the changes required are straightforward to find and correct.

Yes, but I mean changes not only in syntax, but in program design.

And see yet another comment on that below.

>>> C++0x's new features are essentially all present in D 1.0.
>>  Yes, but C++ doesn't require programmers to change their language, tools and libraries. Such change require a lot of time and efforts. Such effors could be applied to the current projects instead of switching to D. But, if D could afford something else, something that completely missing from C++0x (like non-null reference/pointers, some kind of functional programming (pattern-matching) and so on) than such switching would be much more attractive.
>
> D 1.0 provides a lot of things completely missing in C++0x:
>
> 1) unit tests
> 2) documentation generation
> 3) modules
> 4) string mixins
> 5) template string & floating point parameters
> 6) compile time function execution
> 7) contract programming
> 8) nested functions
> 9) inner classes
> 10) delegates
> 11) scope statement
> 12) try-finally statement
> 13) static if
> 14) exported templates that are implementable
> 15) compilation speeds that are an order of magnitude faster
> 16) unambiguous template syntax
> 17) easy creation of tools that need to parse D code
> 18) synchronized functions
> 19) template metaprogramming that can be done by mortals
> 20) comprehensive support for array slicing
> 21) inline assembler
> 22) no crazy quilt dependent/non-dependent 2 level lookup rules that major compilers still get wrong and for which I still regularly get 'bug' reports because DMC++ does it according to the Standard
> 23) standard I/O that runs several times faster
> 24) portable sizes for types
> 25) guaranteed initialization
> 26) out function parameters
> 27) imaginary types
> 28) forward referencing of declarations

In November 2006 in a Russian developers forum I noticed [1] the following D's advantages:

1) fixed and portable data type sizes (byte, short,...);
2) type properties (like .min, .max, ...);
3) all variables and members have default init values;
4) local variables can't be defined without initial values;
5) type inference in 'auto' declaration and in foreach;
6) unified type casting with 'cast';
7) strict 'typedef' and relaxed 'alias';
8) array have 'length' property and slicing operations;
9) exception in switch if no appropriate 'case';
10) string values in 'case';
11) static constructors and destructors for classes/modules;
12) class invariants;
13) unit tests;
14) static assert;
15) Error as root for all exception classes;
16) scope constructs;
17) nested classes, structs, functions;
18) there aren't macros, all symbol mean exactly what they mean;
19) typesafe variadic functions;
20) floats and strings as template parameters;
21) template parameters specialization.

There are a lot of intersections in our lists ;)

>> I know that you work very hard on D, but D 1.0 took almost 7 years. D 2.0 started in 2007, so final D 2.0 could be in 2014?
>
> Even if it does take that long, D 1.0 is still far ahead, and is available now.

As I can see from your D conf's presentation D 2.0 is in the begining of long road. I've seen from your presentation what will D provide as an ultimate answer to C++ and some others languages.

As for me, D 2.0 is a descendant of D (almost as D is descendant of C++). So it is better to think that now we have modern language D 1.0 and we will have better language D 2.0 in time (may be it is better to chose new name for D 2.0, something like D-Bright ;) ).

And now the key factor to make D successful is creating D 1.0 tools, libraries, docs and applications. And show how D 1.0 outperform C++ and others. If we will made this than D 2.0 will come on the prepared ground.

So it is time for pragmatics to focus on D 1.0 and let language enthusiasts play with D 2.0 prototypes.

[1] http://www.rsdn.ru/forum/message/2222569.aspx

-- 
Regards,
Yauheni Akhotnikau