Jump to page: 1 2 3
Thread overview
Blogpost about the T.init problem
Jul 10, 2018
FeepingCreature
Jul 10, 2018
Dukc
Jul 11, 2018
Dukc
Jul 10, 2018
Meta
Jul 10, 2018
Cym13
Jul 11, 2018
FeepingCreature
Jul 11, 2018
FeepingCreature
Update regarding the Nullable issue
Jul 11, 2018
FeepingCreature
Jul 12, 2018
Simen Kjærås
Jul 12, 2018
FeepingCreature
Jul 11, 2018
Meta
Jul 12, 2018
FeepingCreature
Jul 13, 2018
Cym13
Jul 13, 2018
FeepingCreature
Jul 23, 2018
Nick Treleaven
Jul 27, 2018
FeepingCreature
Jul 29, 2018
Jim Balter
Jul 10, 2018
Bastiaan Veelo
Jul 11, 2018
Ali
Jul 12, 2018
Luís Marques
Jul 12, 2018
Timothee Cour
Jul 11, 2018
Greatsam4sure
Jul 29, 2018
Jim Balter
Jul 11, 2018
Greatsam4sure
Jul 29, 2018
Jim Balter
July 10, 2018
I've written up a short blogpost about the T.init issue.

It is not very enthusiastic.

https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43

Related links:

https://github.com/dlang/phobos/pull/6594 problem with T.init and toString

https://github.com/dlang/phobos/pull/6619 Nullable can't work with types where T.init violates invariants

https://github.com/dlang/dmd/pull/8462 A somewhat sketchy PR to disable invariant on struct ~this
July 10, 2018
On Tuesday, 10 July 2018 at 13:41:56 UTC, FeepingCreature wrote:
> I've written up a short blogpost about the T.init issue.

I believe that whoever wrote that spec meant that the invariant WOULD not need to hold if MyDomainData.init WAS called, but that MyDomainData.init must not be called if this is the case.

It definitely needs clarification if I understood it's intent right.


July 10, 2018
On Tuesday, 10 July 2018 at 13:41:56 UTC, FeepingCreature wrote:
> I've written up a short blogpost about the T.init issue.
>
> It is not very enthusiastic.
>
> https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43
>
> Related links:
>
> https://github.com/dlang/phobos/pull/6594 problem with T.init and toString
>
> https://github.com/dlang/phobos/pull/6619 Nullable can't work with types where T.init violates invariants
>
> https://github.com/dlang/dmd/pull/8462 A somewhat sketchy PR to disable invariant on struct ~this

D's contract programming features have been around since D1 and haven't really been updated to work with newer D2 features (this is no excuse IMO; these issues should have been addressed long ago).

My opinion is that it's a vicious circle; D's contract programming features are underutilized, thus nobody cares enough to put effort into ironing out the bugs, thus contract programming in D is buggy and interacts poorly with other language features, thus D's contract programming features are underutilized.

IMO, if you don't have the knowledge, desire, or time to fix them, the next best thing to do is write articles like these bringing some attention to the various defects of contract programming in D, and/or write DIPs to propose ways to fix it.
July 10, 2018
On Tuesday, 10 July 2018 at 13:41:56 UTC, FeepingCreature wrote:
> I've written up a short blogpost about the T.init issue.
>
> It is not very enthusiastic.
>
> https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43
>
> Related links:
>
> https://github.com/dlang/phobos/pull/6594 problem with T.init and toString
>
> https://github.com/dlang/phobos/pull/6619 Nullable can't work with types where T.init violates invariants
>
> https://github.com/dlang/dmd/pull/8462 A somewhat sketchy PR to disable invariant on struct ~this

First of all I must point that I would very much like to have seen a code actually producing an error in that article. Contrary to what is hinted just taking the struct and putting using it with Nullable or format() caused no error for me and worked as expected. Taking .init explicitely was the only thing that actually caused an error. I'm not saying you didn't experience these issues, but if you want to demonstrate a problem then please demonstrate it.

That said, I may be missing something obvious but what prevents you from overloading the init field?

    struct MyDomainData {
        string username;
        @disable this(); // don't make a MyDomainData() by accident!
        this(string username)
        in(!username.empty) // only non-empty usernames please!
        do { this.username = username; }
        // let's formalise the restriction.
        invariant { assert(!username.empty); }
        string toString() { ... }

        static @property MyDomainData init() {
            return MyDomainData("uninitialized");
        }

        ...
    }

    auto test = MyDomainData.init;  // There, no error

Of course that value means nothing but .init isn't meant to actually mean something anyway, it's just a valid value and that's what that init is proposing, so it shouldn't cause any more bugs than empty .init in a normal case.

July 10, 2018
On Tuesday, 10 July 2018 at 13:41:56 UTC, FeepingCreature wrote:
> I've written up a short blogpost about the T.init issue.
>
> It is not very enthusiastic.
>
> https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43


Have you tried giving your invariants a valid  initial value? Change
>   string username;
into
>   string username = "noname";

-Bastiaan
July 11, 2018
On Tuesday, 10 July 2018 at 13:41:56 UTC, FeepingCreature wrote:
> I've written up a short blogpost about the T.init issue.
>
> It is not very enthusiastic.
>
> https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43

Somehow, this is the type of problem, i thought point 1 in the vision document is aimed to solve
https://wiki.dlang.org/Vision/2018H1

"1. Lock down the language definition: D is a powerful language but its definition is not precise enough. A number of subtleties can only be assessed only by running the compiler, not by perusing the specification. This semester we are pushing for a better, more precise, and more complete specification of the D language."

ensuring that the language features are coherent together

July 11, 2018
On Tuesday, 10 July 2018 at 21:08:32 UTC, Cym13 wrote:
> First of all I must point that I would very much like to have seen a code actually producing an error in that article. Contrary to what is hinted just taking the struct and putting using it with Nullable or format() caused no error for me and worked as expected.

To reproduce the format issue, try to print the struct with writefln!"%s"(MyDomainType()).

To reproduce the Nullable issue, you need to slightly modify the struct. In Phobos, Nullable will (due to an abundance of caution) refuse to initialize the struct if the default constructor is disabled; also you need a destructor. However, for this it is enough to use any type that has a destructor, so that an implicit struct destructor is generated. For verbosity, I'll write it out:


struct MyDomainData {
    string username;

    this(string username) @safe
    in(!username.empty) // only non-empty usernames please!
    do { this.username = username; }

    // let's formalise the restriction.
    invariant { assert(!username.empty); }

    string toString() { return null; }

    ~this() @safe { }
}

Then just stick it in a Nullable. No explicit .init needed.

> That said, I may be missing something obvious but what prevents you from overloading the init field?
>
>     struct MyDomainData {
>         string username;
>         @disable this(); // don't make a MyDomainData() by accident!
>         this(string username)
>         in(!username.empty) // only non-empty usernames please!
>         do { this.username = username; }
>         // let's formalise the restriction.
>         invariant { assert(!username.empty); }
>         string toString() { ... }
>
>         static @property MyDomainData init() {
>             return MyDomainData("uninitialized");
>         }
>
>         ...
>     }
>
>     auto test = MyDomainData.init;  // There, no error
>
> Of course that value means nothing but .init isn't meant to actually mean something anyway, it's just a valid value and that's what that init is proposing, so it shouldn't cause any more bugs than empty .init in a normal case.

That would work, it's just a really horrible hack and I hate it. We're constructing a fictitious domain value that passes our invariants while having zero correspondence to the real world, *just to pass our invariants*. It's an obvious sign of a language issue.
July 11, 2018
On Wednesday, 11 July 2018 at 07:30:59 UTC, FeepingCreature wrote:
> Then just stick it in a Nullable. No explicit .init needed.

To clarify this point some more, since on reflection it's ambiguous: you might well say that "well yeah, the default constructor returns an invalid value, no shit it breaks." The semantics of Nullable are weird here though - Nullable!S constructs an S while pretending to not contain an S. The deeper problem is that there is straight up *no way* to implement Nullable correctly in a way that lets it handle types with @disabled this(); without using pointers there's no way to bypass S's destructor, and any implementation of Nullable that uses T.init explicitly dies when D tries to destruct it.

> That would work, it's just a really horrible hack and I hate it. We're constructing a fictitious domain value that passes our invariants while having zero correspondence to the real world, *just to pass our invariants*. It's an obvious sign of a language issue.

Furthermore, note that this limits the amount of invariants we can define. For instance, we can't define an invariant that says that a value has to be registered in a central table somewhere - since our fictional value obviously won't be. Better to do bool isInitialized = false, and that's already crappy.
July 11, 2018
Destructors are not called for fields embedded in unions.

On the one hand this is a horrible, horrible hack. On the other, whee!
July 11, 2018
On Tuesday, 10 July 2018 at 15:10:21 UTC, Dukc wrote:
> It definitely needs clarification if I understood it's intent right.

https://github.com/dlang/dlang.org/pull/2418
« First   ‹ Prev
1 2 3