April 18, 2005
>>I mean, if you want to shutdown, you can do it easily - don't quench assertion failures, how hard is that?
>>
>>OTOH, if assert was unquenchable, there would be no way not to shutdown, 
> 
> 
> Exactly!  Now you're getting it.
> 
> 
>>and I'm always pro-choice :)
> 
> 
> Like ... fclose() shouldn't always close the file if I don't want it to?
>      ... sometimes I might not want function X to return any value but
> sometimes I might?

wtf?? Of course assert should always do the same thing (throw something), I'm just saying I want a choice whether to terminate the app or not.


> The purpose of assert, the reason it exists, is to shutdown programs when
> the programmer chooses to.

Couldn't have said it better myself. But, you don't want to give the programmer a choice when to shutdown..


>>BTW, why shouldn't assert be used to check data? If you look at
>>http://www.digitalmars.com/d/dbc.html
>>it would seem that I'm not the only one that thinks it's ok to do so (and to catch those errors, too).. I mean, an error in data somewhere means an error in logic somewhere else, anyway..
> 
> Duh?! Of course it checks data, but it ought to check *output* data and not
> *input* data. The output data is a result of *your* coding and you need to
> check to see if you implemented the algorithm correctly. That is what
> assert is designed for.

Where did you get that (output data only)?

http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.1.html
checks input data

http://www.digitalmars.com/d/dbc.html
checks input and output data

http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html
checks input and output data..

I mean, a pre-condition is by definition an input data check, I think?


> The input data may or may not have come from your
> code. It could have come from external sources such as users of your
> program. You shouldn't crash a program with assert if the input data is
> bad. You may crash it by some other mechanism though. Assert is a debugging
> mechanism; that is, it is used to find bugs (specifically your coding
> errors) before people get to use your program. A production program, one
> compiled with the -release switch, will not execute any assert statements
> in your code.

Duh?!

But, if it was possible to detect all bugs, this whole conversation would be pointless, as assertion errors would never occur anyway, so, obviously they can occur even after a lot of testing when used in production (assuming you don't disable them, which is a good idea, if you ask me). When they do, I totally agree that the default thing should be to abort. OTOH, I totally don't agree that one should not have the choice at all of trying to recover. I know that theoretically, that defeats the purpose of asserts, but I still want to be able to do it. For example,

void main(char[][] args)
{
    for (int a=0; a<args.length; a++) {
        try {
	        (new Processor()).process(args[a].dup);
        } catch (Object o) {
             // an error occurred, display it to user
        }
    }
}

Now, if I know that Processor and all its libraries don't use any global variables at all (and it is possible to be 100% sure of this), I am in effect restarting the whole application for each file, even when there aren't any errors. So, there is nothing to be gained by aborting. Get it?

I can just see how you'll say that it's stupid to continue with an application that has bugs. But just recently, I had an app that aborted on errors. I was asked by the client to change how it behaves and to continue on errors. The reason there were errors was that double doesn't have enough precision to handle the data they had, so in some cases it was not possible to satisfy some post-conditions (it was not even a bug as such, it simply turned out that some data wasn't possible to handle at all). Still, they wanted to continue processing other data. Now, what I am supposed to say? "Here's the new version, sorry, but I had to disable all internal error checking, because D is such a terrific language it doesn't allow me to continue, so please double-check all the output.." ???


xs0
April 18, 2005
On Mon, 18 Apr 2005 09:15:22 +0200, xs0 wrote:

>>>I mean, if you want to shutdown, you can do it easily - don't quench assertion failures, how hard is that?
>>>
>>>OTOH, if assert was unquenchable, there would be no way not to shutdown,
>> 
>> Exactly!  Now you're getting it.
>> 
>>>and I'm always pro-choice :)
>> 
>> Like ... fclose() shouldn't always close the file if I don't want it to?
>>      ... sometimes I might not want function X to return any value but
>> sometimes I might?
> 
> wtf?? Of course assert should always do the same thing (throw something), I'm just saying I want a choice whether to terminate the app or not.

Then don't use assert.

>> The purpose of assert, the reason it exists, is to shutdown programs when the programmer chooses to.
> 
> Couldn't have said it better myself. But, you don't want to give the programmer a choice when to shutdown..

By "programmer" I was referring to the person who wrote the assert statement, not the person who is attempting to catch it. In other words, The purpose of assert, the reason it exists, is to shutdown programs when the programmer who coded the assert statement has decided to. That is, the assert statement does the shutting down because its coder has already decided that's the proper thing to do.

>>>BTW, why shouldn't assert be used to check data? If you look at
>>>http://www.digitalmars.com/d/dbc.html
>>>it would seem that I'm not the only one that thinks it's ok to do so
>>>(and to catch those errors, too).. I mean, an error in data somewhere
>>>means an error in logic somewhere else, anyway..
>> 
>> Duh?! Of course it checks data, but it ought to check *output* data and not *input* data. The output data is a result of *your* coding and you need to check to see if you implemented the algorithm correctly. That is what assert is designed for.
> 
> Where did you get that (output data only)?
> 
> http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.1.html checks input data
> 
> http://www.digitalmars.com/d/dbc.html
> checks input and output data
> 
> http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html checks input and output data..

Just because people have used assert to validate input data doesn't mean that this is best practice. Remember, asserts only apply to debug editions of the application. So if you are not running a debug edition, and you only use asserts for input data validation, then you have no input data validation. Not a good idea, IMNSHO.

Input data really ought to be validated by mechanisms other than asserts, so that they can at least run in production editions of the application.

> I mean, a pre-condition is by definition an input data check, I think?

Not always, and a pre-condition does not always have to use asserts. Also, "in" blocks and "out" blocks are stripped off production editions of the application (-release switch). In other words, they are only used in debug editions of your application.

Not all pre-conditions inspect input data. They could be used to inspect the environment, or the state of global variables, etc... But the important consideration is that they are used to catch mistakes *during* the time the application is being developed. Once the application is shipped as a production edition, you must rely on other ways to detect runtime errors; do not rely on contract programming techniques to catch mistakes in production code.

>> The input data may or may not have come from your
>> code. It could have come from external sources such as users of your
>> program. You shouldn't crash a program with assert if the input data is
>> bad. You may crash it by some other mechanism though. Assert is a debugging
>> mechanism; that is, it is used to find bugs (specifically your coding
>> errors) before people get to use your program. A production program, one
>> compiled with the -release switch, will not execute any assert statements
>> in your code.
> 
> Duh?!
> 
> But, if it was possible to detect all bugs, this whole conversation would be pointless, as assertion errors would never occur anyway, so, obviously they can occur even after a lot of testing when used in production (assuming you don't disable them, which is a good idea, if you ask me).

I never mentioned the possibility of detecting *all* bugs. I said that use of asserts is designed to catch logic errors. I did not say that using asserts will catch every logic error in your code.

One can detect logic errors by validating the output of functions/algorithms against known values or complementary algorithms. You cannot always detect logic errors by inspecting input data, as the input data could have come from sources outside of your application's control.

> When they do, I totally agree that the default thing should be to abort. OTOH, I totally don't agree that one should not have the choice at all of trying to recover. I know that theoretically, that defeats the purpose of asserts, but I still want to be able to do it. For example,
> 
> void main(char[][] args)
> {
>      for (int a=0; a<args.length; a++) {
>          try {
> 	        (new Processor()).process(args[a].dup);
>          } catch (Object o) {
>               // an error occurred, display it to user
>          }
>      }
> }
> 
> Now, if I know that Processor and all its libraries don't use any global variables at all (and it is possible to be 100% sure of this), I am in effect restarting the whole application for each file, even when there aren't any errors. So, there is nothing to be gained by aborting. Get it?

If asserts have been used in a proper manner, that is, used to trap logic errors, and the application catches an error "catch(Object o) ..." then you can be sure of at least two things: you are still debugging the application, and a logic error somewhere in the application has been found. There is something useful to be gained in aborting the application at this point; namely that it can be repaired while still in development. Get it?

> I can just see how you'll say that it's stupid to continue with an application that has bugs. But just recently, I had an app that aborted on errors. I was asked by the client to change how it behaves and to continue on errors. The reason there were errors was that double doesn't have enough precision to handle the data they had, so in some cases it was not possible to satisfy some post-conditions (it was not even a bug as such, it simply turned out that some data wasn't possible to handle at all). Still, they wanted to continue processing other data. Now, what I am supposed to say? "Here's the new version, sorry, but I had to disable all internal error checking, because D is such a terrific language it doesn't allow me to continue, so please double-check all the output.." ???

To use your own words "it was not even a bug as such". What you have experienced is a client-sponsored change or clarification in the business rules of the application. So no, you don't disable all internal error checking. Instead, you implement the new business specification for the application. I hoped you charged them for the upgrade ;-)

-- 
Derek
Melbourne, Australia
18/04/2005 5:44:21 PM
April 18, 2005
(Disclaimer: I'm not going to start a war about this. :-) I am however
interested in pursuing this for a small while.)

Walter wrote:
> "Georg Wrede" <georg.wrede@nospam.org> wrote in message news:4262E94B.400@nospam.org...
> 
>> Say we decide that (int64_max_value - 1) is an official NAN-INT.
>> And for the signed, (int64_max_value/2 -1) would be the value.
>> 
>> Questions:
>> 
>> 1) Can anybody give a thoroughly solid reason why we _cannot_ skip
>> using these particular values as "NAN"s? (In other words, can
>> someone pretend that we really (even in theory) will actually need
>> _all_ 64bit integer values in production code?)
> 
> We can't. 64 bit ints are often used, for example, to implement fixed
> point arithmetic. Furthermore, NANs work best when the hardware is
> set up to throw an exception if they are used.

One could argue that if someone uses (64bit) fixed point arithmetic in a field where there is a risk for approaching (our newly invented NAN, i.e. int64_max_value - 1) illegal values, then one should be using 128bit for that particular purpose instead anyway. (Similar holds for signed, too.)

And, that actually is the whole problem of my suggestion. I expect it to be monstrously difficult to get "them" to see, that this is a valid idea -- now that we suddenly have "very big" integer types at our disposal.

One could use the exact same arguments against "wasting" the bit patterns of floating NANs. (And there are truckloads of individual bit patterns wasted there!)

----

To implement this, all we need are two things:

1) A new fetch instruction that traps this particular bit pattern in hardware. (I estimate, on a 64bit CPU, this should take less than 500 gates -- pretty small compared to some of the other "new" (and IMHO less pressing) features.)

2) Compiler industry to agree to use this whenever we are fetching this as an rvalue. (The "regular" fetch would still exist, for all other purposes (i.e. when the 64bit entity represents whatever else than a 64bit int)).

And while we're at it, of course the same for 128bit ints.

The compiler would use the "new" fetch only where it does not know for sure that the variable has been initialised. So, for example loops would be free to wrap around. (Not that I'd want them to.)

-----

So, technically this would be trivial and cheap to implement. All we need is the will to do it.

That will has to be aroused somehow. Maybe Walter or Matthew could take this up in CUJ, or Dr.Dobb's? -- I'd even be happy to assist in the writing, or countering the counter arguments you two might get! (The baseball bat.)

<pr-talk-mode>

You'd get some extra fame for raising hell about this, too. No matter which side wins at the end. And all that fame is needed the day we start pushing D with a vengeance.

Or maybe I should get Andy Koenig raving about this instead?

</pr-talk-mode>

This is an important issue, and (as so many times in history) when the means to do something about it become only gradually possible, it often is unduely hard to get everybody to see that "hey, we can already do it".

>> 2) Could it be possible to persuade the "C99 kings" to adopt this
>> practice?
> 
> I just think that no way would that ever happen.
> 
>> 3) If so, could we/they persuade to have chip makers implement
>> hardware traps for these values? (As today null checks and of/uf
>> are done?)

Oh, and incidentally, I've figured out how to extend this to 128bit, 256bit, etc. on 64bit machines.

> The hardware people could do it by adding an "uninitialized" bit for
> each byte, much like the parity bit. Then, a hardware fault could be
> generated when an "uninitialized" memory location is read. This won't
> break existing practice.

Way too complicated.

Oh, and about practice: we wouldn't break any existing code _that_is_not_broken_already_.

For this new setup to break a single program:

First, somebody has to be un-rigorous about initialising his variables, second, the guy has to be operating on values pretty near wrap-around. Now, I do see that used, but only for chip testing, or other very special purposes. (And somebody else doing uint math relying on underflow for home-made "temporary" signed math ought to be shot anyway.)

Besides, this would of course be trappable and quenchable. :-)

If not (gasp) also switchable with a pragma.

>> 4) Is it possible at all to have the Old Farts, who hold the keys
>> to Programming World, to become susceptible to our demands?
> 
> LOL.

I've had ministers of the Cabinet do what I want. It's just a matter of making them see.

And the thing to see here is in it's entirety: 64bit is suddenly so big that we really and honestly can actually _afford_ to waste a single value. -- Which never has happened before (with 32, 16, 8bits).
April 18, 2005
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Georg Wrede schrieb am Mon, 18 Apr 2005 12:13:25 +0300:
> (Disclaimer: I'm not going to start a war about this. :-) I am however
> interested in pursuing this for a small while.)

>>> 1) Can anybody give a thoroughly solid reason why we _cannot_ skip
>>> using these particular values as "NAN"s? (In other words, can
>>> someone pretend that we really (even in theory) will actually need
>>> _all_ 64bit integer values in production code?)
>> 
>> We can't. 64 bit ints are often used, for example, to implement fixed point arithmetic. Furthermore, NANs work best when the hardware is set up to throw an exception if they are used.
>
> One could argue that if someone uses (64bit) fixed point arithmetic in a field where there is a risk for approaching (our newly invented NAN, i.e. int64_max_value - 1) illegal values, then one should be using 128bit for that particular purpose instead anyway. (Similar holds for signed, too.)
>
> And, that actually is the whole problem of my suggestion. I expect it to be monstrously difficult to get "them" to see, that this is a valid idea -- now that we suddenly have "very big" integer types at our disposal.
>
> One could use the exact same arguments against "wasting" the bit patterns of floating NANs. (And there are truckloads of individual bit patterns wasted there!)
>
> ----
>
> To implement this, all we need are two things:
>
> 1) A new fetch instruction that traps this particular bit pattern in hardware. (I estimate, on a 64bit CPU, this should take less than 500 gates -- pretty small compared to some of the other "new" (and IMHO less pressing) features.)
>
> 2) Compiler industry to agree to use this whenever we are fetching this as an rvalue. (The "regular" fetch would still exist, for all other purposes (i.e. when the 64bit entity represents whatever else than a 64bit int)).
>
> And while we're at it, of course the same for 128bit ints.
>
> The compiler would use the "new" fetch only where it does not know for sure that the variable has been initialised. So, for example loops would be free to wrap around. (Not that I'd want them to.)
>
> -----
>
> So, technically this would be trivial and cheap to implement. All we need is the will to do it.
>
> That will has to be aroused somehow. Maybe Walter or Matthew could take this up in CUJ, or Dr.Dobb's? -- I'd even be happy to assist in the writing, or countering the counter arguments you two might get! (The baseball bat.)

<snip>

I can only wholeheartedly agree and support anyone trying to add NAN-int support.

The lack of NAN-int has caused me some really hard to trace bugs.

Thomas


-----BEGIN PGP SIGNATURE-----

iD8DBQFCY4Bm3w+/yD4P9tIRAhMzAJ9koZsZUmJtdwF1gsGJD/bKHLfvbwCdHxfG
DHpohE8qxnHg/SK5935Oz1Q=
=VyVL
-----END PGP SIGNATURE-----
April 18, 2005
>>Of course assert should always do the same thing (throw something), I'm just saying I want a choice whether to terminate the app or not.
> 
> Then don't use assert.

We're going in circles here.. I want to use assert, because assert is exactly the thing that should be used for checking the stuff I want to check. For example:

if (a<b) {
   c=(a+b)*0.5;
   assert(a<c && c<b);
} else {
   throw ..;
}

I guess you agree that an assert is valid here, and that the assertion is not buggy, nor is the code? It is still possible that the assert triggers an error, though. Now, I don't see why I need to use something else, just because I want to give others that use this code a choice to shutdown or not.

Can't you see that if assert errors are unquenchable, you can't ever leave them in code after debugging, because it is always theoretically possible that you (or someone else using your code) will want not to abort, and they don't have that choice?

For the umpteenth time - don't quench assert errors, if you don't want to. If you want to abort anyway, why should it also be enforced in the language?


> By "programmer" I was referring to the person who wrote the assert
> statement, not the person who is attempting to catch it. In other words,
> The purpose of assert, the reason it exists, is to shutdown programs when
> the programmer who coded the assert statement has decided to. That is, the
> assert statement does the shutting down because its coder has already
> decided that's the proper thing to do.

That's a bit simplistic, if you ask me.. Would you use a library that formatted your disk if you ever pass it invalid parameters? Just killing one's app can do even more damage.. I think you assume too much, we're not living in some theoretical ideal world, where aborting is always the right thing to do.


> Just because people have used assert to validate input data doesn't mean
> that this is best practice. Remember, asserts only apply to debug editions
> of the application. So if you are not running a debug edition, and you only
> use asserts for input data validation, then you have no input data
> validation. Not a good idea, IMNSHO.

Whatever you use asserts for, if you disable them, you don't have that validation, so it's not a good idea to disable them in the first place.  And if I do leave them on, I want control over my apps lifecycle, not the language. (OTOH, if you do want to abort, there's nothing stopping you from doing so)


> Input data really ought to be validated by mechanisms other than asserts,
> so that they can at least run in production editions of the application.

I though the idea was to use other mechanisms where you expect invalid data to be possible, and to use asserts where you don't?


>>I mean, a pre-condition is by definition an input data check, I think?
> 
> Not always, and a pre-condition does not always have to use asserts. Also,
> "in" blocks and "out" blocks are stripped off production editions of the
> application (-release switch). In other words, they are only used in debug
> editions of your application.

Not always, not always. I agree. It's you that is claiming that something is always true, like that an assert error should abort the app. Generally yes, but not always!


> Not all pre-conditions inspect input data. They could be used to inspect
> the environment, or the state of global variables, etc... 

How are those not input data? (and if they're really not, why are they being checked?)


> But the important
> consideration is that they are used to catch mistakes *during* the time the
> application is being developed. Once the application is shipped as a
> production edition, you must rely on other ways to detect runtime errors;
> do not rely on contract programming techniques to catch mistakes in
> production code.

So what would you have me do?

version(DEBUG) {
   assert(...);
} else {
   if (...) throw ...;
}

What is wrong with using CP in production code? If there is a contract, it should be obeyed even after you decide to label the code "production"? I mean, since when is more checking a bad thing? The only reason to disable it at all is for performance, which may or may not be what one prefers over the other.


> I never mentioned the possibility of detecting *all* bugs. I said that use
> of asserts is designed to catch logic errors. I did not say that using
> asserts will catch every logic error in your code.

So, is it not better to leave them on in production, too? That way, the remaining errors will at least get detected..

I mean, your reasoning is weird:
- you want debug editions to be forced to abort on assert errors, and
- you want to disable assert in production, which is the only place where it matters whether aborting is done or not


> If asserts have been used in a proper manner, that is, used to trap logic
> errors, and the application catches an error "catch(Object o) ..." then you
> can be sure of at least two things: you are still debugging the
> application, and a logic error somewhere in the application has been found.
> There is something useful to be gained in aborting the application at this
> point; namely that it can be repaired while still in development.

Perhaps, but perhaps not. As I tried to demonstrate with the example that followed, there was nothing to repair (and it obviously was not still in development). At least, there was nothing to repair in the code that threw the assert error, nor in any code that used it. All I did was add that catch(Object), so processing would continue with other files. If you had it your way, I'd have to rewrite hundreds of asserts, and the only thing I'd gain is more bloat (like 80 characters per assert) and a lot of wasted time.


xs0
April 18, 2005
On Mon, 18 Apr 2005 12:52:11 +0200, xs0 wrote:

[snip]
> I mean, your reasoning is weird:

Whatever ... We obviously don't agree with each other and we are unable to convince the other of our 'rightness', so let's stop wasting bandwidth and our colleagues' patience. Instead, we really ought to agree to disagree and get on with our work.

-- 
Derek Parnell
Melbourne, Australia
http://www.dsource.org/projects/build
18/04/2005 9:26:56 PM
April 18, 2005
Derek Parnell wrote:
> On Mon, 18 Apr 2005 12:52:11 +0200, xs0 wrote:
> 
> [snip]
> 
>>I mean, your reasoning is weird:
> 
> 
> Whatever ... We obviously don't agree with each other and we are unable to
> convince the other of our 'rightness', so let's stop wasting bandwidth and
> our colleagues' patience. Instead, we really ought to agree to disagree and
> get on with our work.
> 

Well, a few posts ago you said:

> I would have thought that if a plug-in fails (CP error) then
> *only* the plug-in should fail and not the application that is
> hosting it.

so I don't agree we disagree :) It would just seem that we moved from what we agreed on to assert specifics, which we don't seem to agree on.

I would like to get to the bottom of our disagreement and resolve it, but of course, feel free not to continue our discussion, if you don't want to. Or, we can move it to e-mail, mine is included with all my posts.


xs0
April 18, 2005
On Mon, 18 Apr 2005 14:25:17 +0200, xs0 wrote:

>Or, we can move it to e-mail, mine is included with all my posts.

I just tried your email address but got the message "Could not resolve domain". I sent it to 'xs0' using the domain of 'xs0.com'

-- 
Derek Parnell
Melbourne, Australia
18/04/2005 11:23:00 PM
April 18, 2005
That's odd. I think I need to change my domain provider, some other people had problems visiting my site, too..

Try with mslenc at the Google's mail domain, which starts with g, ends with mail and there's nothing inbetween, while its TLD is .com :)


xs0

Derek Parnell wrote:
> On Mon, 18 Apr 2005 14:25:17 +0200, xs0 wrote:
> 
> 
>>Or, we can move it to e-mail, mine is included with all my posts.
> 
> 
> I just tried your email address but got the message "Could not resolve
> domain". I sent it to 'xs0' using the domain of 'xs0.com'
> 
April 19, 2005
Perhaps there sould be something more allowed as a body to the assert statement.  For example, if the statement is simpy...

assert(x==1);

then the compiler could conside that to be a case where if x is not equal to 1, the program should crash and tell you what went wrong rather that to risk running under unexpected conditions.

On the other hand, if it said...

assert(x==1){x=2; writeln("assigning the value ",2," to the variable named f.");}

This way, if the code was compiled as a release version, no error message would be displayed at all (unless a compiler option specified to show "all" assert errors in the release version( but would be displayed in the debug version. Then the assert would cause x to get a new value and a line of text written to the current or default output device.

This would allow a sort of "sorf assert" where the error handling would actually be the body of the assert statement.

Okay, did that make any sense at all?  Sorry if it didn't.

TZ

"Sean Kelly" <sean@f4.ca> wrote in message news:d3udnj$29cd$1@digitaldaemon.com...
> In article <d3s81s$isa$1@digitaldaemon.com>, Ben Hinkle says...
> >
> >I'm not sure how to differentiate principle and practice. For example
> >  int return1(){ return 0; } // written by an intern
> >  void user_code() {
> >    int x = return1();
> >    assert( x == 1 );
> >    printf("I got a 1.\n");
> >  }
> >Now the code above will assert every time and obviously no real code would look exactly like that but it's not uncommon to see asserts check something that if it fails can be easily recovered from. Is returning 0 from a function that says it returns 1 a contract violation? yes. Is it a big deal? it depends.
>
> This is somewhat of a slippery slope.  To me, preconditions guarantee the criteria for which a function should succceed, and postconditions guarantee that nothing unpredictable has happened in generating that result.  One of the terrific things about contracts is that I don't need to wrap every function call in an error recovery framework to have a reasonable guarantee that it has done what it's supposed to.  Can many contract violations be recovered from in practice?  Certainly.  But to build a language on that assuption, IMO, violates the core principals of DBC.  At the very least, I would like to have the option that contract violations are unrecoverable (this would be trivial with my suggestion of throwing auto classes, as it's largely a library solution anyway). Then it would be up to the client to specify recoverability based on project requirements.  Though this has me leaning towards specifying recovery on a per-thread basis... perhaps a property of the Thread class that defaults based on a global flag?
>
>
> Sean
>
>