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

Reply via email to