DIP 1009--Improve Contract Usability--Preliminary Review Round 1

MysticZach via Digitalmars-d digitalmars-d at puremagic.com
Thu Jun 22 11:57:40 PDT 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


More information about the Digitalmars-d mailing list