February 05, 2015
On Thursday, 5 February 2015 at 00:24:15 UTC, Andrei Alexandrescu wrote:
> I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407:
>
>             auto opSlice(size_t low, size_t high)
>             in
>             {
>                 assert(low <= high);
>             }
>             body
>             {
>                 import std.range : take;
>                 return this[low .. $].take(high - low);
>             }
>
> which of course trivially boils down to:
>
>             auto opSlice(size_t low, size_t high)
>             {
>                 assert(low <= high);
>                 import std.range : take;
>                 return this[low .. $].take(high - low);
>             }
>
> What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere?
>
> I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues.
>
>
> Andrei

Various things.

1/ the initial is overly long because the styling is wasteful.

void foo() in {
  ...
} body {
  ...
}

Is simply one line more than not using contracts.

2/ The semantic is not 100% equivalent (well at least the intended semantic) as the in contract should be chosen based on the static type while the implementation on the dynamic one. That mean the contract should tun in the caller.

I don't think this is what DMD does currently, but that is what is intended. See for instance :
https://issues.dlang.org/show_bug.cgi?id=12247
https://issues.dlang.org/show_bug.cgi?id=6857
February 05, 2015
On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:
> On 2/4/15 4:40 PM, Jonathan Marler wrote:
>> On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:
>>> Contracts can be read by tools, and they are part of the function
>>> signature. Contracts should be encouraged and increased, not discouraged.
>>>
>>> Bye,
>>> bearophile
>>
>> Not to mention that contracts can be removed by the compiler at compile
>> time.
>
> Same about asserts. -- Andrei

assert run in the callee, in contract SHOULD (but currently don't) run in the caller.

That do not create the same optimization opportunities (unless inlining occurs, making the caller and the caller one).
February 05, 2015
On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:
> On 2/4/15 4:40 PM, Jonathan Marler wrote:
>> On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:
>>> Contracts can be read by tools, and they are part of the function
>>> signature. Contracts should be encouraged and increased, not discouraged.
>>>
>>> Bye,
>>> bearophile
>>
>> Not to mention that contracts can be removed by the compiler at compile
>> time.
>
> Same about asserts. -- Andrei

Only if the function is inlined.  The function variables are unknown at compile time so there's no way for the function to compile it away (unless the optimizer can see every single call to the function).  If you make the caller responsible for the assert then it can determine whether or not it needs to perform it at runtime.

Then what about chaining contracts.  If a function has an out contract saying that the return value will be between a certain range, and you use that same variable in another function that requires it to be in the same range, you can compile away any assert after the first one. This is trivial to do with contracts.  You could do it without contracts I suppose, but would be much more brittle (every single return location would have to have the same assert for example)


February 05, 2015
On Thursday, 5 February 2015 at 00:43:04 UTC, Andrei Alexandrescu wrote:
> Yah I concede this is a good point. Yet we're looking at an actual liability and are supposed to look at some vague possible future benefit. -- Andrei

There only a benefit because the coding style for contract is ridiculous. Let's fix the right problem here.
February 05, 2015
On Wed, Feb 04, 2015 at 04:24:14PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
> I'm seeing another idiom that seems to become fashionable. Consider this
> excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407:
> 
>             auto opSlice(size_t low, size_t high)
>             in
>             {
>                 assert(low <= high);
>             }
>             body
>             {
>                 import std.range : take;
>                 return this[low .. $].take(high - low);
>             }
> 
> which of course trivially boils down to:
> 
>             auto opSlice(size_t low, size_t high)
>             {
>                 assert(low <= high);
>                 import std.range : take;
>                 return this[low .. $].take(high - low);
>             }

I disagree.

Putting the assert in the contract means you're putting the onus on the *caller* to ensure parameters are sane. An assert inside the function body should not be vetting function arguments; that's the wrong use of assert. Asserts inside the function body should be checking for sanity *within* the function body.

Requirements on parameter values are something that the *caller* should ensure, and therefore should be in the in-contract, so that the documentation will include it, and readers of the code will know what are the correct arguments to pass (they should not need to read the function body to know this).

The fact that currently in-contracts generate the asserts in the callee rather than the caller (which is probably what led you to your conclusions) is a long-standing mis-implementation of DbC that, one could hope, will finally get fixed now that it is receiving some spotlight. In-contracts should be generated in the *caller*, so that any breach of contract will fail on the caller's side. This is a particularly major problem in shared libraries: when you ship a library, you generally compile it with -release, but since in-contracts are emitted in the callee's body, the asserts are skipped in -release mode, so the result is that there is *no* DbC in the shipped library. This alone puts a big dent in the usefulness of DbC in D, reducing it to nothing more than pretty (or, in this case, not-so-pretty!) syntax for what's otherwise nothing more than a glorified assert.


T

-- 
"I suspect the best way to deal with procrastination is to put off the procrastination itself until later. I've been meaning to try this, but haven't gotten around to it yet. " -- swr
February 05, 2015
On 2/4/15 4:47 PM, deadalnix wrote:
> 1/ the initial is overly long because the styling is wasteful.
>
> void foo() in {
>    ...
> } body {
>    ...
> }
>
> Is simply one line more than not using contracts.

Would introduce an exception to our brace-on-its-line rule.

I need to take issue with "that code is not using contracts". Using assert _is_ using contracts.

> 2/ The semantic is not 100% equivalent (well at least the intended
> semantic) as the in contract should be chosen based on the static type
> while the implementation on the dynamic one. That mean the contract
> should tun in the caller.

Yah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.


Andrei
February 05, 2015
On 2/4/15 4:50 PM, Jonathan Marler wrote:
> On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:
>> On 2/4/15 4:40 PM, Jonathan Marler wrote:
>>> On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:
>>>> Contracts can be read by tools, and they are part of the function
>>>> signature. Contracts should be encouraged and increased, not
>>>> discouraged.
>>>>
>>>> Bye,
>>>> bearophile
>>>
>>> Not to mention that contracts can be removed by the compiler at compile
>>> time.
>>
>> Same about asserts. -- Andrei
>
> Only if the function is inlined.

Non-debug mode removes asserts statically. -- Andrei


February 05, 2015
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:
> On 2/4/15 4:47 PM, deadalnix wrote:
>> 1/ the initial is overly long because the styling is wasteful.
>>
>> void foo() in {
>>   ...
>> } body {
>>   ...
>> }
>>
>> Is simply one line more than not using contracts.
>
> Would introduce an exception to our brace-on-its-line rule.
>
> I need to take issue with "that code is not using contracts". Using assert _is_ using contracts.
>

My definition of an in contract is a condition that the caller is responsible to verify.  It appears that your definition is that it's a condition on a function argument (doesn't matter who is responsible).  I believe that Walter's definition of Contract programming is the definition I'm referring to.  I remember watching one of his talks on contract programming and the performance/optimization benefits he talked about would only apply if a contract made the callee responsible for the asserts.

The responsible party, caller/callee matters.  As far as I know, D is the first language to allow a function to make the caller responsible for verifying an assert.  Even before I saw this in D, I always wondered why no languages provided a way specify this. H.S. Teoh had a good response on why it matters to specify caller/callee so I'll refer to his response instead of re-hashing what he already said.
February 05, 2015
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:
> Yah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.
>

Putting the contract in the caller is not only useful for overridable functions.

1/ If a lib is compiled in without contract, but your code is compiled with, you get the in contract to run when you call library code, but not the assert within the function.

2/ The optimizer see the properties of the argument when they get to the in contract. This information is lost in the callee, unless inlining goes on. that means the amount of contract the optimizer can remove statically is greater with in contract.
February 05, 2015
On 2/4/15 5:32 PM, deadalnix wrote:
> On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:
>> Yah, I agree "in" is useful for overridable functions. In fact I'd say
>> it's useful _only_ for overridable functions.
>>
>
> Putting the contract in the caller is not only useful for overridable
> functions.
>
> 1/ If a lib is compiled in without contract, but your code is compiled
> with, you get the in contract to run when you call library code, but not
> the assert within the function.
>
> 2/ The optimizer see the properties of the argument when they get to the
> in contract. This information is lost in the callee, unless inlining
> goes on. that means the amount of contract the optimizer can remove
> statically is greater with in contract.

Yah, I understand the potential there. Consider me grudgingly convinced :o). -- Andrei