June 22, 2017
On Thursday, 22 June 2017 at 10:59:18 UTC, Moritz Maxeiner wrote:
> Again, that's not what H.S. Teoh's proposal would do. All it does is install an *implementation agnostic*, *abtract* way to specify contracts into the grammar. Whether that is lowered to assert, or anything else is an implementation detail and it certainly isn't fixed to asserts.

Okay. Then the proposal needs to be accompanied by an explicit description of how to hook into the new semantics. Which is what you provided, but I suppose it would need to be exactly specified. In particular, where exactly is the code for the (optional) user-defined hook to be found? In a separate file, maybe as indicated with a command line option, e.g. `-contractsConfig=myContracts.d`?

> DIP1003 did not introduce an entirely new system, it merely slightly changed an existing sytem.
> DIP1009 *does* introduce several new syntax forms, i.e. adding a whole new system, which means it *also* introduces the responsibility of maintaining backwards compatibility when someone tries to improve contracts again (and then we would have three systems to specify contracts).

Okay, I'm a convert. Although still one big downside is that DbC in D is somewhat impaired, as H.S. Teoh pointed out [1].

[1] http://forum.dlang.org/post/mailman.3554.1498074198.31550.digitalmars-d@puremagic.com

June 22, 2017
On Thursday, 22 June 2017 at 12:54:00 UTC, MysticZach wrote:
> On Thursday, 22 June 2017 at 10:59:18 UTC, Moritz Maxeiner wrote:
>> Again, that's not what H.S. Teoh's proposal would do. All it does is install an *implementation agnostic*, *abtract* way to specify contracts into the grammar. Whether that is lowered to assert, or anything else is an implementation detail and it certainly isn't fixed to asserts.
>
> Okay. Then the proposal needs to be accompanied by an explicit description of how to hook into the new semantics. Which is what you provided, but I suppose it would need to be exactly specified. In particular, where exactly is the code for the (optional) user-defined hook to be found? In a separate file, maybe as indicated with a command line option, e.g. `-contractsConfig=myContracts.d`?

As long as one is doing this, maybe a proposal for user-defined `assert` should be provided too? It'd be interesting to have a dedicated file for user-defined assert and contract configuration. The core idea is to allow *everyone*, from large companies to individual hobbyists, to use `assert`, `in`, and `out`, and have it work the way they want. I would definitely need help writing that DIP.
June 22, 2017
On Thursday, 22 June 2017 at 13:11:12 UTC, MysticZach wrote:
> As long as one is doing this, maybe a proposal for user-defined `assert` should be provided too? It'd be interesting to have a dedicated file for user-defined assert and contract configuration. The core idea is to allow *everyone*, from large companies to individual hobbyists, to use `assert`, `in`, and `out`, and have it work the way they want. I would definitely need help writing that DIP.

:-)
June 22, 2017
On Thursday, 22 June 2017 at 12:54:00 UTC, MysticZach wrote:
> On Thursday, 22 June 2017 at 10:59:18 UTC, Moritz Maxeiner wrote:
>> Again, that's not what H.S. Teoh's proposal would do. All it does is install an *implementation agnostic*, *abtract* way to specify contracts into the grammar. Whether that is lowered to assert, or anything else is an implementation detail and it certainly isn't fixed to asserts.
>
> Okay. Then the proposal needs to be accompanied by an explicit description of how to hook into the new semantics. Which is what you provided, but I suppose it would need to be exactly specified. In particular, where exactly is the code for the (optional) user-defined hook to be found? In a separate file, maybe as indicated with a command line option, e.g. `-contractsConfig=myContracts.d`?

I would put the selection mechanics and prefinded semantics into druntime, e.g. under core.contracts.
In particular I'm thinking about Insister [1] and if it makes sense to put something like that in core.contracts, expose a `IInsister theContractChecker` that can be overwritten at runtime and have the compiler lower contract checks to `theContractChecker.insist` calls.
I'm not sure if that is the best way to go forward, but it would be nice for the configurability to be remain in language constructs without requiring addition of compiler options, I think.

>
>> DIP1003 did not introduce an entirely new system, it merely slightly changed an existing sytem.
>> DIP1009 *does* introduce several new syntax forms, i.e. adding a whole new system, which means it *also* introduces the responsibility of maintaining backwards compatibility when someone tries to improve contracts again (and then we would have three systems to specify contracts).
>
> Okay, I'm a convert. Although still one big downside is that DbC in D is somewhat impaired, as H.S. Teoh pointed out [1].

Yay!
Regarding the location of contract checking: Yes, though I agree with him that a fix for that need not be part of this DIP. If this DIP cleanly separates contract specification from contract implementation, we can address it separately. In particular, if something like Insister gets chosen as the framework, then the issue of contract checking not occuring on the caller site should be fixable simply by changing where the compiler injects the lowered `theContractChecker.insist` into.

[1] http://forum.dlang.org/post/pdqdaktjifgajiwnpxaz@forum.dlang.org
June 22, 2017
On Thursday, 22 June 2017 at 13:11:12 UTC, MysticZach wrote:
> On Thursday, 22 June 2017 at 12:54:00 UTC, MysticZach wrote:
>> On Thursday, 22 June 2017 at 10:59:18 UTC, Moritz Maxeiner wrote:
>>> Again, that's not what H.S. Teoh's proposal would do. All it does is install an *implementation agnostic*, *abtract* way to specify contracts into the grammar. Whether that is lowered to assert, or anything else is an implementation detail and it certainly isn't fixed to asserts.
>>
>> Okay. Then the proposal needs to be accompanied by an explicit description of how to hook into the new semantics. Which is what you provided, but I suppose it would need to be exactly specified. In particular, where exactly is the code for the (optional) user-defined hook to be found? In a separate file, maybe as indicated with a command line option, e.g. `-contractsConfig=myContracts.d`?
>
> As long as one is doing this, maybe a proposal for user-defined `assert` should be provided too? It'd be interesting to have a dedicated file for user-defined assert and contract configuration. The core idea is to allow *everyone*, from large companies to individual hobbyists, to use `assert`, `in`, and `out`, and have it work the way they want. I would definitely need help writing that DIP.

Upon reflection, that is exactly what my Insister proposal is :p
The reason it's not called Asserter, btw, is that assert is a
a) a keyword, and
b) is already deeply entrenched with the concept of Errors (bugs), in D
and that `enforce`, is also de facto established for Exceptions (user input error),
so `insist` would then be a configurable chooser between the two.
June 22, 2017
On Thursday, 22 June 2017 at 12:21:29 UTC, MysticZach wrote:
>
> I understand. Thus, a better DIP would suggest reimplementing D's DbC system altogether. Because as it is, they are little more than syntax dressing, which happens to be less convenient that just writing out the asserts in the first place. They're more like syntax _vinegar_ than sugar. Which explains why hardly anyone uses them. Why write this:
>
> int fun(int a)
> in { assert (a); }
> do {
>     return a;
> }
>
> ...when you could just do this:
>
> int fun(int a) {
>    assert(a);
>    return a;
> }
>

My recollection is that the most significant reason to use contracts in D is because of contract inheritance. There's a lot of focus in this discussion on normal functions, when I would say that contracts really aren't even needed.

So a more useful situation to consider then is:

class Foo
{
    int fun(int a)
    in {
        assert(a > 0 && a < 10);
    }
    body {
        return a;
    }
}

class Bar : Foo
{
    int fun(int a)
    in {assert(a > 0);}
    body {
        return a;
    }
}

I would say keep the current behavior for backwards compatibility (maybe with the body/do change), but also allow the following code:

class Foo
{
    int fun(int a)
    {
        in {
            assert(a > 0 && a < 10);
        }
        return a;
    }
}

class Bar : Foo
{
    int fun(int a)
    {
        in {assert(a > 0);}
        return a;
    }
}

where the compiler would effectively re-write this into the code above. You wouldn't need to make a change to interfaces since they don't have bodies anyway.


June 22, 2017
On Thu, Jun 22, 2017 at 01:33:17PM +0000, Moritz Maxeiner via Digitalmars-d wrote: [...]
> Regarding the location of contract checking: Yes, though I agree with him that a fix for that need not be part of this DIP. If this DIP cleanly separates contract specification from contract implementation, we can address it separately.
[...]

Not to mention, if we restrict the scope of this DIP to just syntax improvement, it stands a better chance of being accepted by Walter & Andrei. Stuffing too many things into it stands the risk of having the whole thing rejected because of just one or two items that they deem undesirable.


T

-- 
Trying to define yourself is like trying to bite your own teeth. -- Alan Watts
June 22, 2017
On 22.06.2017 16:08, jmh530 wrote:
> 
> My recollection is that the most significant reason to use contracts in D is because of contract inheritance. There's a lot of focus in this discussion on normal functions, when I would say that contracts really aren't even needed.

They are needed if you want to write contracts, and there are legitimate reasons to want to write contracts.
June 22, 2017
On Thu, Jun 22, 2017 at 02:08:32PM +0000, jmh530 via Digitalmars-d wrote: [...]
> My recollection is that the most significant reason to use contracts in D is because of contract inheritance. There's a lot of focus in this discussion on normal functions, when I would say that contracts really aren't even needed.
[...]

I agree that contract inheritance is an important use case, but FWIW, I write contracts in my non-class methods all the time.  They are useful to document to the user (i.e., me 3 months later after I forgot the details of the code) what exactly the function expects / assumes, and for catching accidental wrong usages.  Coupled with judiciously crafted unittests, this is invaluable for weeding out bugs in my code both during coding and also prevents regressions / future wrong usages of the function later.


T

-- 
People tell me that I'm paranoid, but they're just out to get me.
June 22, 2017
On Thursday, 22 June 2017 at 14:08:32 UTC, jmh530 wrote:
> My recollection is that the most significant reason to use contracts in D is because of contract inheritance. There's a lot of focus in this discussion on normal functions, when I would say that contracts really aren't even needed.
>
> So a more useful situation to consider then is:
> [...]
> I would say keep the current behavior for backwards compatibility (maybe with the body/do change), but also allow the following code:
>
> class Foo
> {
>     int fun(int a)
>     {
>         in {
>             assert(a > 0 && a < 10);
>         }
>         return a;
>     }
> }
>
> class Bar : Foo
> {
>     int fun(int a)
>     {
>         in {assert(a > 0);}
>         return a;
>     }
> }

The existing proposal allows this, and goes further and allows removing the unnecessary brackets after `in`:

class Foo
{
    int fun(int a)
    {
        in assert(a > 0 && a < 10);
        return a;
    }
}
class Bar : Foo
{
    // override
    override int fun(int a)
    {
        in assert(a > 0);
        return a;
    }
}

Some people don't like the cognitive dissonance of seeing `in` inside the function. It really doesn't look that bad to me, and I'm glad to have a little support for the idea. But there are a couple more considerations. First, classes in D are not as popular as they are in some other languages, because of how powerful regular structs have become. I'd want to get more feedback on the value of improving a syntax (assuming it is clearly an improvement, which several people so far disagree with) that is only really valuable in cases that aren't used that much.

There are other questions too. The syntax is only one of three possible reasons contracts in D aren't that popular. The second reason is that the specific implementation, i.e. the  "backend", currently has limited support as described by H.S. Teoh [1]. The third reason is more abstract and harder to pin down, which is that some things are just more attractive in theory than they are in practice. The question is, even with the best possible syntax, and the best possible implementation, how much total value can `in` and `out` contracts add to language? How much more total use would they see?

If we knew in advance that the answer to the third question is, "People wouldn't use them that much," then we might spare ourselves the effort of improving them. We could more or less drop the issue as a lost cause. But I suppose the premise of this DIP is that it's worth it to try to find out. It also looks like there will be a separate DIP for reimplementing the backend, so this one will focus, as it already does, on the syntax.

That said, H.S. Teoh's version of the above code would look like this:

class Foo
{
    int fun(int a)
    in(a > 0 && a < 10)
    {
        return a;
    }
}
class Bar : Foo
{
    override int fun(int a)
    in(a > 0)
    {
        return a;
    }
}

I'm leaning towards pushing this one, as it simply hasn't gotten the pushback that mine has so far. I do have a problem with it, which is that the checking logic is mingled in with the grammar. This doesn't usually happen in D, which normally requires you to explicitly write `assert` in order to assert something. Here, `in` becomes grammatically equivalent to an `assert` expression, but one which is only allowed in the function signature. At minimum, I can say that the reception for this idea has been more positive than for mine. But I do appreciate the support :-}

[1] http://forum.dlang.org/post/mailman.3554.1498074198.31550.digitalmars-d@puremagic.com