August 01, 2014
On 8/1/2014 8:18 AM, Assaf Gordon via Digitalmars-d wrote:
> As Walter said, it's alarming how many programs fail to handle such cases
> (though D is pretty solid in that regard).

One of the very cool things about the ranges+algorithms style of programming is things like I/O don't get mixed up in code that operates on data.

It means that detecting I/O failures only have to be coded in a relatively concentrated and small handful of places rather than sprinkled throughout the code.

Couple this with the exception model of reporting errors, and we have a fairly robust system of not silently overlooking I/O failures.
August 01, 2014
On 8/1/2014 6:12 AM, Dicebot wrote:
> ok, can this be considered a good summary of using assertions/contracts for
> services where risk of entering undefined state is unacceptable?
>
> 1) never use `assert` or contracts in actual application code, use `enforce`
> instead
> 2) never use `enforce` in library code unless it does actual I/O, use contracts
> instead
> 3) always distribute both release and debug builds of libraries and always run
> tests in both debug and release mode
>
> Does it make sense? Your actual recommendation contradict each other but it is
> best what I was able to combine them into.

What makes me hesitate about use of enforce() is its high runtime cost. It's not just the computation, but the call stack above it is affected by enforce() being throwable and allocating via the GC.

Secondly, enforce() is about recoverable errors. Program bugs are simply NOT recoverable errors, and I cannot recommend using them for that purpose. I've argued for decades with people who insist that they can write code that recovers from unknown programming bugs.

August 01, 2014
On Friday, 1 August 2014 at 17:53:03 UTC, Timon Gehr wrote:
> On 08/01/2014 07:39 PM, Andrei Alexandrescu wrote:
>>...
>>
>
> I did what I though was right. Do what you like. I'm off.

I feel you, this whole thread is extremely frustrating.

Having your augment consistently dismissed by "I see no difference" or "That is misuse" is frustrating to say the least.
August 01, 2014
On Friday, 1 August 2014 at 19:47:35 UTC, Tofu Ninja wrote:
> Having your augment consistently dismissed by "I see no

*argument not augment :/
August 01, 2014
On Fri, Aug 01, 2014 at 12:05:00PM -0700, Walter Bright via Digitalmars-d wrote:
> On 8/1/2014 8:18 AM, Assaf Gordon via Digitalmars-d wrote:
> >As Walter said, it's alarming how many programs fail to handle such cases (though D is pretty solid in that regard).
> 
> One of the very cool things about the ranges+algorithms style of programming is things like I/O don't get mixed up in code that operates on data.
[...]

Not to mention, it lets you *really* unittest your code thoroughly, because it isolates each separate stage of the processing into its own self-contained unit, with clearly-defined standard interconnects. Your unittest can therefore easily hook up with the unit's interfaces, and inject arbitrary inputs to the unit and run arbitrary tests on its output -- without needing such hackery as redirecting stdout just so you can confirm correct computation of a numerical result, for example.

In the traditional imperative programming style, you often have code that has loops within loops within loops, with complex interactions between each loop body and its surrounding context. It's generally impossible (or very hard) to extricate the inner loop code from its tightly-coupled context, which means your unittest will have a hard time "reaching into" the innards of the nested loops to verify the correctness of each piece of code.  Often, the result is that rather than testing each *unit* of the code, you have to do a holistic test by running the entire machinery of nested loops inside a sandbox and capturing its output (via stdout redirection, or instrumenting dependent subsystems, etc.) -- hardly a *unit* test anymore! -- and still, you have the problem that there are too many possible code paths that these nested loops may run through, so it would be hard to have any confidence that you've covered sufficiently many paths in the test. You're almost certain to miss important boundary cases.


T

-- 
The irony is that Bill Gates claims to be making a stable operating system and Linus Torvalds claims to be trying to take over the world. -- Anonymous
August 01, 2014
On Friday, 1 August 2014 at 17:19:09 UTC, Sebastiaan Koppe wrote:
> If assertions are disabled in release builds, and you specifically instruct the compiler to build one, are you not assuming that the assertions will hold?
>
> Then what is wrong with extending those assumptions to the optimizer?
>
> Unless the assertions trigger in debug build, you will not end up with bugs in the release.

To support: it seems to me that assert() is nothing more than an assume() with a check.

Why the check bothers you if the assumption is still true? Compiler just like to do overwork in debug builds, let's grant that pleasure to it.
August 01, 2014
On Friday, 1 August 2014 at 17:43:27 UTC, Timon Gehr wrote:
> On 08/01/2014 07:19 PM, Sebastiaan Koppe wrote:

> The debug and the release build may be subjected to different input and hence traverse different traces of abstract states. It is not valid to say that an assertion will never fail just because it hasn't failed yet.

Yes, but is the same for the C apps. There, you have no assertion in the release build, the release build is optimized (I imagine very few would use -O0 on it...), then the sefault happens.

Good luck with the debugger and find the bug in the source code....

This is why debug builds exist, to reproduce problems and to investigate the bugs.
August 01, 2014
On 8/1/2014 1:02 PM, H. S. Teoh via Digitalmars-d wrote:
> Not to mention, it lets you *really* unittest your code thoroughly,
> because it isolates each separate stage of the processing into its own
> self-contained unit, with clearly-defined standard interconnects. Your
> unittest can therefore easily hook up with the unit's interfaces, and
> inject arbitrary inputs to the unit and run arbitrary tests on its
> output -- without needing such hackery as redirecting stdout just so you
> can confirm correct computation of a numerical result, for example.
>
> In the traditional imperative programming style, you often have code
> that has loops within loops within loops, with complex interactions
> between each loop body and its surrounding context. It's generally
> impossible (or very hard) to extricate the inner loop code from its
> tightly-coupled context, which means your unittest will have a hard time
> "reaching into" the innards of the nested loops to verify the
> correctness of each piece of code.  Often, the result is that rather
> than testing each *unit* of the code, you have to do a holistic test by
> running the entire machinery of nested loops inside a sandbox and
> capturing its output (via stdout redirection, or instrumenting dependent
> subsystems, etc.) -- hardly a *unit* test anymore! -- and still, you
> have the problem that there are too many possible code paths that these
> nested loops may run through, so it would be hard to have any confidence
> that you've covered sufficiently many paths in the test. You're almost
> certain to miss important boundary cases.

I agree and want to amplify this a bit. When a function accepts ranges as its input/output parameters, then the function tends to be a template function. This means that it becomes easy for the unittests to "mock up" ranges and feed them to the function to test it.

I've used this to great success with Warp.

August 01, 2014
On Friday, 1 August 2014 at 20:16:29 UTC, eles wrote:

> Yes, but is the same for the C apps. There, you have no assertion in the release build, the release build is optimized (I imagine very few would use -O0 on it...), then the sefault happens.
>

In c the assert is just a check, no assume, the Microsoft compiler even has its own __assume separate from assert.
August 01, 2014
Am 01.08.2014 22:16, schrieb eles:
> On Friday, 1 August 2014 at 17:43:27 UTC, Timon Gehr wrote:
>> On 08/01/2014 07:19 PM, Sebastiaan Koppe wrote:
>
>> The debug and the release build may be subjected to different input
>> and hence traverse different traces of abstract states. It is not
>> valid to say that an assertion will never fail just because it hasn't
>> failed yet.
>
> Yes, but is the same for the C apps. There, you have no assertion in the
> release build, the release build is optimized (I imagine very few would
> use -O0 on it...), then the sefault happens.
>

But there checks are not optimized away because of assert.
assert(x != NULL);
if(x != NULL) { ... }
in C the if check won't be optimized away in NDEBUG builds, in equivalent D code it would, because the assert would make the compiler assume that x will never be NULL at that point.

Cheers,
Daniel