August 25, 2018
On Saturday, 25 August 2018 at 12:16:06 UTC, Laeeth Isharc wrote:
> On Saturday, 25 August 2018 at 10:52:04 UTC, Chris wrote:
>> On Friday, 24 August 2018 at 19:26:40 UTC, Walter Bright wrote:
>
>
> There are quite a few different sorts of concerns raised on this thread and they are linked by how people feel not by logic.  I have a lot of respect for Shachar technically but I personally found the way he expressed his point of view a bit odd and unlikely to be effective in achieving whatever it is his goal was, also bearing in mind he doesn't speak for Weka.
>
> It might be helpful to go through the concerns and organise them based on logical ordering because an outburst of emotion won't translate in itself into any kind of solution.

You can approach things rationally, make a list of the issues, have a big discussion again.

and nothing will change.



August 25, 2018
On Wednesday, 22 August 2018 at 11:59:37 UTC, Paolo Invernizzi wrote:
> Just found by chance, if someone is interested [1] [2].
>
> /Paolo
>
> [1] https://gitlab.com/mihails.strasuns/blog/blob/master/articles/on_leaving_d.md
> [2] https://blog.mist.global/articles/My_concerns_about_D_programming_language.html

I find Dicebot's article resonates quite strongly with me. I have been using D for hobby projects (i.e. not a lot of code) for about 3 years. During that time I found a handful of compiler bugs. An average programmer like me shouldn't be able to find bugs in the compiler so frequently.

And there are other problems, like language features interact weirdly, unhelpful/misleading error messages. All of this really gives me an impression that D is an immature language.

I think this is a pretty big problem, and I think it has not been given enough attention (never appeared in bold in the vision documents), probably until now.

So what if, we just forget about @safe, @nogc, and stuff like that for while, do a feature freeze and try our best to fix all the bugs, and rough corners?
August 25, 2018
On Saturday, August 25, 2018 7:33:47 AM MDT Shachar Shemesh via Digitalmars- d wrote:
> On 25/08/18 10:56, Walter Bright wrote:
> > On 8/24/2018 6:34 AM, Shachar Shemesh wrote:
> >> No, unlike what I suggest, that doesn't work without carefully reviewing every single place you put it to see whether the constructor actually supports destructing a partially constructed object.
> >
> > All D objects are default-initialized before the constructor sees it (unlike C++). A destructor should be able to handle a default-initialized object.
>
> I'm not talking about a default initialized object. I'm talking about an object where the constructor started running, but not to completion.
>
> With that said, this statement is, I think, representative of the Lego problem D has. All D objects? Really? Even this one?
>
> struct A {
>    int a;
>
>    @disable this();
>    @disable init;
>
>    this(int number);
>    ~this();
> }
>
> If you allow a feature to be disabled, you really need to keep in mind that feature might be well and truly disabled.

As I understand it, it's not actually possible to disable the init value. Even if bodies are provide for the constructor and destructor (so that they don't give you errors), you just end up with an error like

q.d(14): Error: no identifier for declarator init

You could replace that with something like

    @disable void init();

but that's only legal because declaring a member named init has never been made illegal even though it's generally been agreed upon (by most of the core devs anyway) that it should be. The way D is designed, there _must_ be an init value. The closest that you can get to disabling it is the

    @disable this();

line which just disables default initialiation. The init value still gets used when constructing the object, and it can still be used explicitly.

If void initialization of member variables worked the way that some folks think that it should - including Andrei and Walter:

https://issues.dlang.org/show_bug.cgi?id=11331 https://issues.dlang.org/show_bug.cgi?id=11817

then I think that that would definitely be an example that would fit the point that you're trying to make (since they you have to worry about the constructor partially setting values on top of garbage and then trying to destroy that correctly), but at least for the moment, it doesn't actually work. Having to worry about destructors running on void initialized objects is a similar problem, but not quite the same, since that doesn't involve an exception being thrown from a constructor. Regardless, even if a type is designed such that its init value can be properly destroyed, and you don't have to worry about void initialization, it can't be all that hard to design it such that the destructor won't work properly if the constructor doesn't complete properly.

What all of this makes me think of though is a similar problem that FeepingCreature loves to bring up and complain about, which is that invariants that consider the init value to be invalid (e.g. if the invariant checks that a member variable is non-null) blow up in your face if the type has a destructor, because the invariant gets run before the destructor, and member variables that are pointers will of course be null in the init value. And while disabling default initialization helps, it doesn't fix the problem because of code that explicitly uses the init value. To work around this, he's come up with some weird solution using unions that's probably going to break on him at some point (though if I understand correctly, he's changed std.typecons.Nullable to use it, which makes it a lot less likely that it's going to break). But really, having an invariant that fails for the init value is generally a recipe for disaster, much as it's easy to see why it would be desirable for stuff like pointers.

What's worse is that once void initialization is involved, an invariant is almost certainly going to fail, because the invariant gets called before opAssign. And that's the number one reason that I never use invariants in structs anymore.

In any case, all of that is really a tangent with regards to init values, but it's definitely a sign of how some of the stuff around init values, constructors, and destructors doesn't really play well together. And sadly, it's really not that hard to get into a state where your destructor is going to have serious problems if it's run. In general, any place where D was designed around the idea that something would _always_ be there (e.g. init values and default initialization) but we've then later added the ability to get around it (e.g. void initialization or @disable) has tended to not play well with everything else and has caused some fun problems.

- Jonathan M Davis



August 25, 2018
On 8/25/2018 6:33 AM, Shachar Shemesh wrote:
> If you allow a feature to be disabled, you really need to keep in mind that feature might be well and truly disabled.

Disabling default initializations is not @safe, and that means taking responsibility for it not being default initialized.

It's like turning off array bounds checking. Then it's up to you to ensure no buffer overflows are happening.

On a pragmatic note, what you're asking for is a set of nested try blocks, one for each field with a throwing constructor, as opposed to one try block around the entire function. This is an expensive proposition in terms of performance. You'll need to weigh that very carefully against saving the default zero initialization of the struct, which is very efficient.
August 25, 2018
On 8/25/2018 7:37 AM, Jonathan M Davis wrote:
> In general, any place where D was
> designed around the idea that something would _always_ be there (e.g. init
> values and default initialization) but we've then later added the ability to
> get around it (e.g. void initialization or @disable) has tended to not play
> well with everything else and has caused some fun problems.

It's why that stuff isn't allowed in @safe code, and hence one should realize one is taking responsibility from the compiler for ensuring the correctness. D expects someone writing @system code to have a much greater awareness of how the language and the machine works.

If you remove the blade guards from the table saw, more things can be done with it, but you'll need to take much greater care using it.
August 25, 2018
On 8/25/2018 6:32 AM, Timon Gehr wrote:
> (Or at least, not wrong. Using e.g. `void*` instead of an incompatible type would already be an improvement.)

Making it void* is a reasonable idea.
August 25, 2018
On 8/25/2018 3:52 AM, Chris wrote:
> On Friday, 24 August 2018 at 19:26:40 UTC, Walter Bright wrote:
>> Every programmer who says this also demands new (and breaking) features.
> "Every programmer who..." Really?

You want to remove autodecoding (so do I) and that will break just about every D program in existence. For everyone else, it's something else that's just as important to them.

For example, Shachar wants partially constructed objects to be partially destructed, a quite reasonable request. Ok, but consider the breakage:

  struct S {
    ~this() {}
  }

  class C {
    S s;

    this() nothrow {}
  }

I.e. a nothrow constructor now must call a throwing destructor. This is not some made up example, it breaks existing code:

  https://github.com/dlang/dmd/pull/6816

If I fix the bug, I break existing code, and apparently a substantial amount of existing code. What's your advice on how to proceed with this?
August 25, 2018
On Saturday, 25 August 2018 at 20:52:06 UTC, Walter Bright wrote:
> I.e. a nothrow constructor now must call a throwing destructor. This is not some made up example, it breaks existing code:
>
>   https://github.com/dlang/dmd/pull/6816
>
> If I fix the bug, I break existing code, and apparently a substantial amount of existing code. What's your advice on how to proceed with this?

Deprecated message and allow it (nothrow and @safe\system checks) for a year or two? Guaranteed destructor call is important enough to actually bother with this IMO. Nothrow and other attribute deduction could also be a temporary option.
August 25, 2018
On Saturday, 25 August 2018 at 20:52:06 UTC, Walter Bright wrote:
> If I fix the bug, I break existing code, and apparently a substantial amount of existing code. What's your advice on how to proceed with this?

At least for the transition period, I'd have attributes only apply to the user-specified code and infer them for the actual full constructor. (We can still print a deprecation warning if they don't match.) —David
August 25, 2018
On Friday, 24 August 2018 at 17:12:53 UTC, H. S. Teoh wrote:
> I got bitten by this just yesterday.  Update dmd git master, update vibe.d git master, now my vibe.d project doesn't compile anymore due to some silly string.d error somewhere in one of vibe.d's dependencies. :-/

Welcome to my life with D for the past 2 years. You can not rely on D as new features break old ones or create regressions. You can also not rely on its packages, because new features or changes break packages. Or packages that depend on each other break.

In the end, the answer is simply, you can not rely on D. Unless you want to stick with one compiler version and write every feature yourself.

Other languages also suffer from issues like this but they get fixed so fast that in general the impact is rarely noticed. With D you can be stuck waiting days or weeks! or spending hours fixing it yourself. Again and again ...

So your time doing actual work is absorbed by constant fixing D issues. Some will say that contributing to a open source program is the cost to pay but when you have the choice between well established and stable languages and D... That cost very fast becomes: Lets use C/C++/Rust/Go/... And it is saying a lot when young languages like Rust and Go gave me less trouble then D.

D has potential but this push for BetterC, better C++ integration, more DIPS down the pipeline... When is enough, enough! It feels like D is more some people their personal playground to push and try out new features then a actually well supported and stable language.

You can play around with D at home or for small project but for long term projects, where you bank your company's future on D, you need to be crazy.