July 29, 2014
On 7/28/2014 1:49 PM, "Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang@gmail.com>" wrote:
> You might want to assert() that you have enough headroom in a statically
> allocated buffer when testing. Say you assert that the buffer is never more than
> 50% full for normal loads. You obviously don't want the -release build to make
> such an assumption!

You're misunderstanding and misusing assert.

'assume' is completely redundant with 'assert'.

To have different debug builds, use debug statements.
July 29, 2014
On Tuesday, 29 July 2014 at 01:07:44 UTC, Walter Bright wrote:
> You're misunderstanding and misusing assert.
>
> 'assume' is completely redundant with 'assert'.

Nope, you are conflating what is proven by what is not proven an by what cannot be proven.

If it is proven, then you don't need headroom at all!
July 29, 2014
I find it worrying that you take so lightly on basic correctness. Asserts are entirely probabilistic in nature. What you are arguing for is a regime where a single bad assert can result in the user's disk getting wiped even though you had protections in place in the code without asserts that would have prevented it. That is horrible.

With 500 asserts and a 99.9% chance of a single assert not contradicting the program you have ~40% chance of having contradictions.

I guess that makes D a @safe language...
July 29, 2014
"Ola Fosheim Gr"  wrote in message news:kpfxpgdpakuqrdziawxl@forum.dlang.org...

> I find it worrying that you take so lightly on basic correctness. Asserts are entirely probabilistic in nature. What you are arguing for is a regime where a single bad assert can result in the user's disk getting wiped even though you had protections in place in the code without asserts that would have prevented it. That is horrible.

The idea is you test your code with assertions enabled, and then only use '-release' when you are sure your program functions correctly.

If you are doing critical work or do not trust program input, either do not disable assertions or use a tool like enforce that does not get disabled in release mode. 

July 29, 2014
On Tuesday, 29 July 2014 at 06:35:06 UTC, Daniel Murphy wrote:
> The idea is you test your code with assertions enabled, and then only use '-release' when you are sure your program functions correctly.
>
> If you are doing critical work or do not trust program input, either do not disable assertions or use a tool like enforce that does not get disabled in release mode.

This is what makes D design by contract almost useless when writing network services :( Unless you have 100% code coverage (and I mean literally 100%) you can't be sure enough to disable assertions with arbitrary user input. And even if you have full coverage you still can't be sure

I guess that qualifies as "critical work" but, really, any work is critical when failure results in money loss.
July 29, 2014
On 7/29/2014 12:00 AM, Dicebot wrote:
> On Tuesday, 29 July 2014 at 06:35:06 UTC, Daniel Murphy wrote:
>> The idea is you test your code with assertions enabled, and then only use
>> '-release' when you are sure your program functions correctly.
>>
>> If you are doing critical work or do not trust program input, either do not
>> disable assertions or use a tool like enforce that does not get disabled in
>> release mode.
>
> This is what makes D design by contract almost useless when writing network
> services :( Unless you have 100% code coverage (and I mean literally 100%) you
> can't be sure enough to disable assertions with arbitrary user input. And even
> if you have full coverage you still can't be sure

You can choose to disable assertions with a switch, or not. Having a choice up to you doesn't make it useless.

Also, assertions are not for validating user input.

July 29, 2014
On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
> On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad wrote:
>> If asserts were used as optimization constraints
>
> all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it.
>
> bool foo(int a)
> {
>     //let's handwrite a simple assert
>     if(a >= 0)
>     {
>         exit(EXIT_FAILURE);
>     }
>     //and then do something.
>     return a < 0;
> }
>
> Of course the compiler is free to rewrite that as
>
> bool foo(int a)
> {
>     if(a >= 0)
>     {
>         exit(EXIT_FAILURE);
>     }
>     return true;
> }
>
> Why should the situation be different if I use the builtin `assert` instead?

The problem is that in release mode, the asserts are removed. It would then be a very big mistake to still take them into account for optimizations, as if they were actually there.

To take your code:

    assert(a >= 0);
    return a < 0;

is equivalent to

    assert(a >= 0);
    return true;

but only in non-release mode. In release mode, this effectively becomes

    return a < 0;

which is _not_ equivalent to

    return true;

I believe this is was Ola is protesting about, and I agree with him. Such optimizations must only happen if the check stays.
July 29, 2014
On Tuesday, 29 July 2014 at 07:31:26 UTC, Walter Bright wrote:
> You can choose to disable assertions with a switch, or not. Having a choice up to you doesn't make it useless.

Yes I know what are options to make it work. I don't know how to make it work "in a good style". This is not just D problem - I feel like something is missing in the design by contract idea, something that actually can make it robust enough to be used without "oh crap" moments.

> Also, assertions are not for validating user input.

This is one of problems. When writing library function you don't exactly know if input is going to be user input. Use enforces - and it won't be possible to optimize away redundant checks. Use assertions and issue may slip uncaught.

It feels like for contracts to really work some good implementation of red-green code zones is necessarily, to be able to distinguish user input call paths from internal ones during compilation time.
July 29, 2014
On Tuesday, 29 July 2014 at 09:40:27 UTC, Marc Schütz wrote:
> On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
>> On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad wrote:
>>> If asserts were used as optimization constraints
>>
>> all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it.
>>
>> bool foo(int a)
>> {
>>    //let's handwrite a simple assert
>>    if(a >= 0)
>>    {
>>        exit(EXIT_FAILURE);
>>    }
>>    //and then do something.
>>    return a < 0;
>> }
>>
>> Of course the compiler is free to rewrite that as
>>
>> bool foo(int a)
>> {
>>    if(a >= 0)
>>    {
>>        exit(EXIT_FAILURE);
>>    }
>>    return true;
>> }
>>
>> Why should the situation be different if I use the builtin `assert` instead?
>
> The problem is that in release mode, the asserts are removed. It would then be a very big mistake to still take them into account for optimizations, as if they were actually there.
>
> To take your code:
>
>     assert(a >= 0);
>     return a < 0;
>
> is equivalent to
>
>     assert(a >= 0);
>     return true;
>
> but only in non-release mode. In release mode, this effectively becomes
>
>     return a < 0;
>
> which is _not_ equivalent to
>
>     return true;
>
> I believe this is was Ola is protesting about, and I agree with him. Such optimizations must only happen if the check stays.

you mean assert(a < 0) or assert(!(a >= 0)) right?

In a correct program (a necessary but not sufficient condition for which is to not violate it's asserts) it is the same.

The program is in error if a > 0, whether the assert is compiled in or not. Running in debug mode can simply mean "check my assumptions".
July 29, 2014
On Tuesday, 29 July 2014 at 10:13:45 UTC, Dicebot wrote:
> This is one of problems. When writing library function you don't exactly know if input is going to be user input. Use enforces - and it won't be possible to optimize away redundant checks. Use assertions and issue may slip uncaught.

I have taken to using versions and enforce for this. Something like:

version(noChecks){} else
{
    version = checks;
}

void foo(int a)
{
    version(checks) enforce(a > 0);
    // do work
}

so the user of the library has to explicitly disable the checks when compiling the library, independent of -release. Also, all functions should document their input assumptions.

Binary libraries is a bit different though, I guess you have to distribute 3 versions: debug, release and release-noChecks