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/[email protected]

Reply via email to