Why D is not popular enough?

Shachar Shemesh via Digitalmars-d digitalmars-d at puremagic.com
Sat Aug 13 22:18:08 PDT 2016


On 14/08/16 03:26, Andrei Alexandrescu wrote:
> On 08/13/2016 05:57 PM, Jonathan M Davis via Digitalmars-d wrote:
>> I'm also tempted to argue that making shared virtually unusable without
>> casting it away would be a good idea
>
> It's a bad idea, no two ways about it. The bummer here is that this is
> the only topic (and one where D gets it right) off of a whole list that
> Shachar gave, which I'll copy below. His slides are at
> http://www.slideshare.net/ShacharShemesh1/dconf-2016-d-improvement-opportunities.
> Is the talk video anywhere?
>
>> - No RAII support, despite the fact everybody here seems to think that
>> D supports RAII.
>
> So that is slide 4. Could you please give a bit of detail?

http://www.digitalmars.com/d/archives/digitalmars/D/What_is_going_on_here_257862.html

>
>> - Recursive const makes many cases where I can use const in C++ (and
>> enjoy the protection it provides) simply mutable in D.
>
> (It's transitive, not recursive.) Can't help much here but note that
> C++'s const being shallow is a source of confusion among beginning
> programmers. It's a matter in which reasonable people may disagree. I
> clearly see how someone used to C++'s const wold feel uncomfortable with
> D's.

I'm quite fine with disagreeing on this point, but I do want to make 
sure we agree on what it is we disagree about.

My view of the C++ const situation is consistent with C++'s philosophy 
about pretty much everything, which is this. "We give you very powerful 
tools to do many things. We do not, however, prevent you from misusing 
them. Caveat emptor".

C++'s "logical constness" may lead to pretty twisted stuff if misused, 
but the flip side is that, when used correctly, it can be used quite 
extensively to give the compiler tools to protect you from mistakes.

D's const, to me (please correct me if I'm wrong), aimed not at helping 
the compiler help the programmer, but at helping the compiler. It 
contains a much stronger guarantee, and accordingly, is applicable in 
much fewer cases.

It is my understanding that we agree on the above. If we do, I can state 
my opinion, and you are most welcome to disagree with it, and we can 
call that matter resolved.

In my experience, D's guarantee is too strong, in that it is too often 
inapplicable. This leads to two bad things happening.

The first is that you can rarely put "const" on anything, meaning you 
lose the power that C++'s guarantee gave you, and not gain enough in return.

The second is that, since it is so rarely applicable, people tend to 
forget implementing the const version of methods, even when those are 
easy. This leads to a situation where, even if const can be applied, it 
is just too much work to weed out the bugs all over the place this will 
cause, and people give up.

Compound this with the total mess that is "inout", and I, personally, 
just gave up. I know I'm not the only one.

>
> The opIndexOpAssign family is intentional and arguably a good thing. The
> semantics of std::map's operator[] are controversial and suboptimal;
> opIndexOpAssign is specially designed to allow efficient dictionaries
> and sparse arrays. If you get to reduce the code we'd definitely want to
> fix whatever bug is there.

I will. I just don't know how long it will take me to get to it. I 
already tried to recreate it simply with two structs and just the 
relevant ops, without success (though, now that I think of it, it might 
have been with a different version than the one that compiles our code).

If you want, since I know you have access, I can send you the line 
number from which this was taken.

Either way, this is just one example out of many where the interaction 
between features creates complex situations that either result in not 
defined (as opposed to undefined) behavior, or result in behavior that 
may be well defined, but is surprising to the programmer.

>
>> - GC. GC. GC. Some more GC.
>
> You mean there's too much of it? We're on that.

Not exactly, but I have nothing to say here which you don't already 
know, so let's leave it at that.

>
>> - Integral type operations promotion and the constant need for casts.
>
> This is... funny coming from a self-proclaimed C++ lover. Anyhow, VRP
> has bugs that we need to fix.

Won't solve my problems unless VRP's scope is significantly enhanced. 
Your book said VRP is only defined to work on the same expression it is 
in. So long as that's the case, it's not a matter of fixing bugs.

Also, I should point out, that I'm not suggesting D allow implicit 
narrowing conversions. Instead, I think D should drop the pretense that 
C expressions should maintain their semantics precisely, and stop 
widening expressions.

I must confess that I have never heard of this rule in C before 
encountering it in D. Any time I needed some expression to take place 
with a width larger than the input arguments, I always casted them.

Since this is still necessary for long, I think dropping this rule won't 
be too big of an issue.

>> - No ref type.
>
> This you need to live with.

Can you expand a little on the rational for that? Also, part of our 
problems with this is that introspection also does not see refs, which 
causes the following two functions to report the same signature:

void func1(int arg);
void func2(ref int arg);


>
> We'd love to make the life easier for Weka,

I'd like to make it clear here that I speak of my own experience. I do 
talk with people, and some of the engineers share some of my criticism. 
However, please don't think that just because I'm more vocal than others 
in Weka, it means that my opinions are shared by all. Please treat my 
posts here as my own.

  but you need to be careful
> when mixing things of the D ethos you don't like but won't change
> (qualifiers, ref) with things that we can improve.
>
> Did you try the .d/.di compile-time table?

Not my task, so what I'm writing here is second hand knowledge from one 
random water cooler talk. Please excuse me if I'm making gross 
misrepresentations of reality here.

 From what I understand, there is a problem with the way imports are put 
in the di files. In particular, take the following code:

import some.struct: SomeStruct;
import some.other.struct: SomeOtherStruct;

SomeStruct func() {
    SomeOtherStruct a(3);
    return a.some;
}

The ideal di for it would be:

import some.struct: SomeStruct;

SomeStruct func();

Sadly, the actual di also contains the totally unnecessary:

import some.other.struct: SomeOtherStruct;

The result is that the di contains too many imports, and no gains are 
made vis compilation times.

Shachar



More information about the Digitalmars-d mailing list