www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - condition stringising in assert

reply "Matthew Wilson" <dmd synesis.com.au> writes:
Can I register yet another request for this long-looked-for feature?

I'm finding it rather painful that the output just prints "Error:
AssertError Failure vector(390)". It's just a PITA.

Can we get this for 1.0?
Jul 13 2004
next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <cd077b$282s$1 digitaldaemon.com>, Matthew Wilson says...
Can I register yet another request for this long-looked-for feature?

I'm finding it rather painful that the output just prints "Error:
AssertError Failure vector(390)". It's just a PITA.

Can we get this for 1.0?

You could always do what I do these days, which is to replace: # assert(a == b); with # if (a != b) throw new Error("a is not equal to b in function f()"); or similar. Actually, I've never been entirely comfortable with assert()s, since they magically disappear in a release build. This is a good thing only if you're sure those asserts are never going to happen. Jill
Jul 13 2004
prev sibling next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Matthew Wilson wrote:

Can I register yet another request for this long-looked-for feature?

I'm finding it rather painful that the output just prints "Error:
AssertError Failure vector(390)". It's just a PITA.

Can we get this for 1.0?


  

Speaking of asserts, another useful feature would be a continue (ie ignore/ignore all) option. That is particularly useful when working in a large group of people and someone stuffs up part of the build that is not very important to you (ie you working on graphics and someone stuff up the sound engine). Although I'm not exactly sure how that would work though. I think the best option (parhaps 2.0) is to allow for our own customisable asserts. That way we can stop things like timers, things over networks and graphics cards and re-start them again when continued. We can then also put up a nice OS based interface to deal with asserts. That is the safest option. -- -Anderson: http://badmama.com.au/~anderson/
Jul 13 2004
next sibling parent reply teqDruid <me teqdruid.com> writes:
void myAssert(bit condition, char[] message)
{
	if (condition)
		throw new myException(message);
}

I'm not sure what it is you're looking for that can't be done with
Exceptions.

On Tue, 13 Jul 2004 23:34:37 +0800, J Anderson wrote:

 Matthew Wilson wrote:
 
Can I register yet another request for this long-looked-for feature?

I'm finding it rather painful that the output just prints "Error:
AssertError Failure vector(390)". It's just a PITA.

Can we get this for 1.0?



  

Speaking of asserts, another useful feature would be a continue (ie ignore/ignore all) option. That is particularly useful when working in a large group of people and someone stuffs up part of the build that is not very important to you (ie you working on graphics and someone stuff up the sound engine). Although I'm not exactly sure how that would work though. I think the best option (parhaps 2.0) is to allow for our own customisable asserts. That way we can stop things like timers, things over networks and graphics cards and re-start them again when continued. We can then also put up a nice OS based interface to deal with asserts. That is the safest option.

Jul 13 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
teqDruid wrote:

void myAssert(bit condition, char[] message)
{
	if (condition)
		throw new myException(message);
}

I'm not sure what it is you're looking for that can't be done with
Exceptions.

  

The thing is the line-number+filename. Now you can do a stack trace but that's not very convenient in many situations, particularly if your working on a different OS which has no general console. Also message assert need to be standardised. Its an extreamly useful tool. Each developer (and they will) should not need to write their own. -- -Anderson: http://badmama.com.au/~anderson/
Jul 14 2004
parent teqDruid <me teqdruid.com> writes:
On Wed, 14 Jul 2004 22:46:12 +0800, J Anderson wrote:

 teqDruid wrote:
 
void myAssert(bit condition, char[] message) {
	if (condition)
		throw new myException(message);
}
}
I'm not sure what it is you're looking for that can't be done with
Exceptions.


  

that's not very convenient in many situations, particularly if your working on a different OS which has no general console.

if the line numbers and filenames were exposed to it, so Exceptions had access to that info.
 
 Also message assert need to be standardised.  Its an extreamly useful
 tool.  Each developer (and they will) should not need to write their own.

Jul 14 2004
prev sibling parent "Matthew Wilson" <dmd synesis.com.au> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:cd0odg$4rp$1 digitaldaemon.com...
 Matthew Wilson wrote:

Can I register yet another request for this long-looked-for feature?

I'm finding it rather painful that the output just prints "Error:
AssertError Failure vector(390)". It's just a PITA.

Can we get this for 1.0?

Speaking of asserts, another useful feature would be a continue (ie ignore/ignore all) option. That is particularly useful when working in a large group of people and someone stuffs up part of the build that is not very important to you (ie you working on graphics and someone stuff up the sound engine). Although I'm not exactly sure how that would work though.

Agreed. I was thinking along the same lines.
 I think the best option (parhaps 2.0) is to allow for our own
 customisable asserts. That way we can stop things like timers, things
 over networks and graphics cards and re-start them again when
 continued.  We can then also put up a nice OS based interface to deal
 with asserts.  That is the safest option.

Sounds useful
Jul 14 2004
prev sibling next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson <dmd synesis.com.au> 
wrote:
 Can I register yet another request for this long-looked-for feature?

 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so it's only you the developer that sees them, in which case you simply open the source and you can see what asserted. That said, when you do something like.. foreach(char[] s; testStrings) { ..etc.. assert(); } the file/line number for the assert does not tell you which testString failed. In which case I have used: foreach(char[] s; testStrings) { ..etc.. if () { printf(""); assert(); } } While on this topic, what does an assert do in a windows full screen 3d app? currently, I assume, it is printing to stderr and terminating the app. Can we over-ride that behaviour? I imagine a full screen 3d app does not have a console or a stderr, plus you want the assert box to popup in front of the full screen display. I have seen commercial games where the error box was hidden by the games main window with no way to see it. I think a global onAssert() method/function that if exists is called on assert would be very useful. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message
news:opsa3k2sce5a2sq9 digitalmars.com...
 On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson <dmd synesis.com.au>
 wrote:
 Can I register yet another request for this long-looked-for feature?

 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so it's only you the developer that sees them, in which case you simply open the source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers? Look through the STLSoft source - in fact grep for "message_assert" - and you'll see just how useful a meaningful message in an assertion can be.
Jul 13 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 14 Jul 2004 10:07:39 +1000, Matthew 
<admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3k2sce5a2sq9 digitalmars.com...
 On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson <dmd synesis.com.au>
 wrote:
 Can I register yet another request for this long-looked-for feature?

 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so it's only you the developer that sees them, in which case you simply open the source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Open source or closed? If it's open source you can open the source and look.
 Look through the STLSoft source - in fact grep for "message_assert" - 
 and you'll
 see just how useful a meaningful message in an assertion can be.

The fact that I can, tells me this is open source, in which case if I got an assert I could open the source and look. Regardless, can you give me an example of when your library would assert. Is it because I called a function with incorrect parameters? or..? Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message
news:opsa3p7mzu5a2sq9 digitalmars.com...
 On Wed, 14 Jul 2004 10:07:39 +1000, Matthew
 <admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3k2sce5a2sq9 digitalmars.com...
 On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson <dmd synesis.com.au>
 wrote:
 Can I register yet another request for this long-looked-for feature?

 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so it's only you the developer that sees them, in which case you simply open the source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Open source or closed? If it's open source you can open the source and look.

Yes, but sometimes the assert condition can be complex. If there's a simple message telling the user immediately what the problem is, then they've saved time. I can't see why that's not an attractive thing? It helps in many circumstances, but costs nothing and does no harm.
Jul 13 2004
next sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
Matthew wrote:

 
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3p7mzu5a2sq9 digitalmars.com...
 On Wed, 14 Jul 2004 10:07:39 +1000, Matthew
 <admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3k2sce5a2sq9 digitalmars.com...
 On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson
 <dmd synesis.com.au> wrote:
 Can I register yet another request for this long-looked-for feature?

 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so it's only you the developer that sees them, in which case you simply open the source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Open source or closed? If it's open source you can open the source and look.

Yes, but sometimes the assert condition can be complex. If there's a simple message telling the user immediately what the problem is, then they've saved time. I can't see why that's not an attractive thing? It helps in many circumstances, but costs nothing and does no harm.

Here are a few message_assert's I've found in src/phobos/etc/c/stlsoft: winstl_message_assert("Attempting to increment an invalid iterator!", NULL != m_handle); winstl_message_assert("Dereferencing end()-valued iterator", 0); unixstl_message_assert("Shared search handle being destroyed with outstanding references!", 0 == cRefs); and it looks generally like these asserts are for cases when the user has incorrectly used the library. I agree for these types of asserts (if they should be asserts) a message helps the user correct their code. But a typical assert Walter uses is something like Internal Error: ..\ztc\cgcod.c 614 which means Walter (not the user) messed up and all he needs are some reproduction steps and the file and line number. Personally I tend to use asserts like you do and consider invalid usage to be assertable where Walter keeps asserts to only internal usage (I think Arcane Jill had also posted that's how she uses asserts). So I think it makes sense to have two different assert mechanisms for these two different usage models. Maybe there should be some sort of "private assert" and "public assert" and the public one has message strings and the private one doesn't. -Ben
Jul 13 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 13 Jul 2004 22:10:02 -0400, Ben Hinkle <bhinkle4 juno.com> wrote:
 Matthew wrote:

 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3p7mzu5a2sq9 digitalmars.com...
 On Wed, 14 Jul 2004 10:07:39 +1000, Matthew
 <admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3k2sce5a2sq9 digitalmars.com...
 On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson
 <dmd synesis.com.au> wrote:
 Can I register yet another request for this long-looked-for 



 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so it's only you the developer that sees them, in which case you simply open the source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Open source or closed? If it's open source you can open the source and look.

Yes, but sometimes the assert condition can be complex. If there's a simple message telling the user immediately what the problem is, then they've saved time. I can't see why that's not an attractive thing? It helps in many circumstances, but costs nothing and does no harm.

Here are a few message_assert's I've found in src/phobos/etc/c/stlsoft: winstl_message_assert("Attempting to increment an invalid iterator!", NULL != m_handle); winstl_message_assert("Dereferencing end()-valued iterator", 0); unixstl_message_assert("Shared search handle being destroyed with outstanding references!", 0 == cRefs); and it looks generally like these asserts are for cases when the user has incorrectly used the library. I agree for these types of asserts (if they should be asserts) a message helps the user correct their code. But a typical assert Walter uses is something like Internal Error: ..\ztc\cgcod.c 614 which means Walter (not the user) messed up and all he needs are some reproduction steps and the file and line number. Personally I tend to use asserts like you do and consider invalid usage to be assertable where Walter keeps asserts to only internal usage (I think Arcane Jill had also posted that's how she uses asserts). So I think it makes sense to have two different assert mechanisms for these two different usage models. Maybe there should be some sort of "private assert" and "public assert" and the public one has message strings and the private one doesn't.

Maybe... I think the crux of it is "what is assert worthy and what is an exception?" A commonly used assert, is one used when a parameter to your API is incorrect. Typically when using Windows C API calls there is an error code returned which says invalid parameter. As we don't use those in D, do we throw an exception OR use an assert in this case? I think in this case an exception allows the user of your API more flexibility. It may not be a fatal error for this particular API call to fail, they may want to catch and handle the exception. Using the above examples, an exception may be valid here...
  winstl_message_assert("Attempting to increment an invalid iterator!", 
 NULL
 != m_handle);

not sure, not really enough context. In other examples an assert may be perfectly valid, like here...
  unixstl_message_assert("Shared search handle being destroyed with
 outstanding references!", 0 == cRefs);

this seems to me to be one too many calls to a free function, probably due to a buggy algorithm/loop they used to call it. Basically what I'm saying is perhaps sometimes we use asserts and should have used an exception and vice-versa. I did voice an idea for an overload function onAssert() so as to modify the behaviour of how it outputs the assert. I don't think that is required any mode, I think if it's an error the end user needs to see it should be an exception. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsa32o5pf5a2sq9 digitalmars.com>, Regan Heath says...
A commonly used assert, is one used when a parameter to your API is 
incorrect. Typically when using Windows C API calls there is an error code 
returned which says invalid parameter. As we don't use those in D, do we 
throw an exception OR use an assert in this case?

We throw an exception, obviously. Otherwise you will never be able to test what happens when the user provides invalid input. Why not? Because in a debug build, the asserts will prevent invalid input from reaching the function, so the horror of that ACTUALLY HAPPENING (with consomate access violations, buffer overflows, whatever) will simply not occur ... in a debug build. So you'll never test it, and never write code to deal with bad user input. But invalid user input will make it through those asserts in a release build. And then guess what's gonna happen after that? Ouch! D is not C. A D assert is not the same thing as C assert. Arcane Jill
Jul 14 2004
prev sibling parent Regan Heath <regan netwin.co.nz> writes:
On Wed, 14 Jul 2004 11:12:44 +1000, Matthew 
<admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3p7mzu5a2sq9 digitalmars.com...
 On Wed, 14 Jul 2004 10:07:39 +1000, Matthew
 <admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa3k2sce5a2sq9 digitalmars.com...
 On Tue, 13 Jul 2004 18:39:05 +1000, Matthew Wilson 


 wrote:
 Can I register yet another request for this long-looked-for 



 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.

 Can we get this for 1.0?

I can't see the point myself. asserts only occur in debug builds, so end users never see them, so


 only you the developer that sees them, in which case you simply open 


 source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Open source or closed? If it's open source you can open the source and look.

Yes, but sometimes the assert condition can be complex. If there's a simple message telling the user immediately what the problem is, then they've saved time. I can't see why that's not an attractive thing? It helps in many circumstances, but costs nothing and does no harm.

The cost is Walters time, the other features/things he does not do while he is doing this. Is this really something you *must* have for 1.0? or is it simply decoration. I think it's decoration as you can already get a 'nice' message by printing then asserting. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cd1tgu$26qd$2 digitaldaemon.com>, Matthew says...

 asserts only occur in debug builds, so end users never see them, so it's
 only you the developer that sees them, in which case you simply open the
 source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Not sure I agree with this. My Deimos library stuff does have asserts, but only because I expect them never to happen. They don't indicate that the library USER has done anything wrong, merely that I have a bug to fix. Fortunately, I am here, and people who discover such bugs can tell me about it. If I were not contactable, it still wouldn't matter too much because Deimos is open source, and so, theoretically, someone ELSE could fix it. But in the circumstance where (a) the library author were not contactable, and (b) the project were not open source, an assert would be a very bad thing to encounter. A throw of an exception (with a suitable error message) would be much more appropriate, methinks. Arcane Jill
Jul 14 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cd2o1k$mru$1 digitaldaemon.com...
 In article <cd1tgu$26qd$2 digitaldaemon.com>, Matthew says...

 asserts only occur in debug builds, so end users never see them, so it's
 only you the developer that sees them, in which case you simply open the
 source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Not sure I agree with this. My Deimos library stuff does have asserts, but only because I expect them never to happen. They don't indicate that the library

 has done anything wrong, merely that I have a bug to fix.

 Fortunately, I am here, and people who discover such bugs can tell me about it.
 If I were not contactable, it still wouldn't matter too much because Deimos is
 open source, and so, theoretically, someone ELSE could fix it.

 But in the circumstance where (a) the library author were not contactable, and
 (b) the project were not open source, an assert would be a very bad thing to
 encounter. A throw of an exception (with a suitable error message) would be

 more appropriate, methinks.

I don't agree. Exceptions are for exceptional conditions, i.e failures, not human errors. If you want to be "strict", then the right thing to do when a DbC condition is violated is to halt. An exception is not the appropriate response.
Jul 14 2004
next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
news:cd2rij$tra$1 digitaldaemon.com...
 "Arcane Jill" <Arcane_member pathlink.com> wrote in message
 news:cd2o1k$mru$1 digitaldaemon.com...
 In article <cd1tgu$26qd$2 digitaldaemon.com>, Matthew says...

 asserts only occur in debug builds, so end users never see them, so it's
 only you the developer that sees them, in which case you simply open the
 source and you can see what asserted.

Nonsense. What about users of libraries, i.e. developers?

Not sure I agree with this. My Deimos library stuff does have asserts, but


 because I expect them never to happen. They don't indicate that the library

 has done anything wrong, merely that I have a bug to fix.

 Fortunately, I am here, and people who discover such bugs can tell me about


 If I were not contactable, it still wouldn't matter too much because Deimos


 open source, and so, theoretically, someone ELSE could fix it.

 But in the circumstance where (a) the library author were not contactable,


 (b) the project were not open source, an assert would be a very bad thing to
 encounter. A throw of an exception (with a suitable error message) would be

 more appropriate, methinks.

I don't agree. Exceptions are for exceptional conditions, i.e failures, not

 errors. If you want to be "strict", then the right thing to do when a DbC
 condition is violated is to halt. An exception is not the appropriate response.

As the man himself says, if you don't want your process to halt when it's actually in an unsound state, what do you want it to do? One more thing: it seems to me that everyone always assumes that assertions are a debug-time feature only. There's absolutely no reason why this should be so, and I've worked on systems where they were always active (albeit they had different actions in debug and release mode).
Jul 14 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

I don't agree. Exceptions are for exceptional conditions, i.e failures, not
human
errors. If you want to be "strict", then the right thing to do when a DbC
condition is violated is to halt. An exception is not the appropriate response.

Eh?
Jul 14 2004
next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cd33r9$1cjn$1 digitaldaemon.com...
 In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

I don't agree. Exceptions are for exceptional conditions, i.e failures, not


errors. If you want to be "strict", then the right thing to do when a DbC
condition is violated is to halt. An exception is not the appropriate


 Eh?

Errors: A human failure to have coded something correctly. Fault: A condition that may legitimately result in the lifetime of a process within the context of its execution environment. Passing a null-pointer is an error. Failure to write to a file through lack of disk space is an exception. In almost all cases, a process should handle an exception, and take remedial action. Of course, one such action is to terminate the process - e.g. when out of memory - but that's rarely the best answer. The point made by Bertrand Meyer is that errors, which reflect coding failures, *not* environmental conditions, should result in termination of the process. Although this seems somewhat extreme, he sagely posits the question "what would you have an erroneous process do?". Is that any clearer?
Jul 14 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cd33r9$1cjn$1 digitaldaemon.com>, Arcane Jill says...
In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

I don't agree. Exceptions are for exceptional conditions, i.e failures, not
human
errors. If you want to be "strict", then the right thing to do when a DbC
condition is violated is to halt. An exception is not the appropriate response.

Eh?

So what's wrong with this then? # Int sqrt(Int x) # { # if (x < 0) throw new IntException("sqrt(x) not defined for x < 0"); # //... # } An assert is DEFINITELY not the right thing here. The input could come from the intermediate result in a long calculation. Whether or not x is negative may not be deducable at compile time. So it's an error, and that's EXACTLY what exceptions are for. And it will only halt the program if the exception is not caught. (Which is fair enough, I think). Anyone canny enough to wrap such calls in a try block can do their own tidy-up. And if they don't they'll get a nice error message. On the other hand, the Int class also supplies some LOW LEVEL functions. Here's one: # uint bigintLLAdd(uint* d, uint* x, uint xLen, uint* y, uint yLen) # in # { # assert(xLen >= yLen); # } whereby the input MUST obey (xLen >= yLen), and if it doesn't then it's a bug on the part of the caller. The assert tells whoever wrote the calling function to fix /their/ bug. This sort of thing I only ever do on seriously low level code, at the pointer and buffer level, where undefined behavior is the guaranteed result of naff input. As Norbert (I think) said, an "in" condition is part of the function's interface. So what do YOU think is the correct thing to do then, in both of these circumstances? And when exactly would you throw an exception? Note that the phrase "exceptional conditions, i.e failures" is nonsense, since "exceptional conditions" does NOT mean the same thing as "failures". (The Latin abbreviation i.e. stands for "id est", which means "that is", "that is to say", or "in other words"). They're called "Exceptions" because they happen in exceptional (that is, rare, uncommon) circumstances. They're not called "Failures", a word which means something completely different. Perhaps you could clarify your meaning? Arcane Jill
Jul 14 2004
next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cd35jt$1fll$1 digitaldaemon.com...
 In article <cd33r9$1cjn$1 digitaldaemon.com>, Arcane Jill says...
In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

I don't agree. Exceptions are for exceptional conditions, i.e failures, not



errors. If you want to be "strict", then the right thing to do when a DbC
condition is violated is to halt. An exception is not the appropriate



Eh?

So what's wrong with this then? # Int sqrt(Int x) # { # if (x < 0) throw new IntException("sqrt(x) not defined for x < 0"); # //... # } An assert is DEFINITELY not the right thing here. The input could come from the intermediate result in a long calculation. Whether or not x is negative may not be deducable at compile time. So it's an error, and that's EXACTLY what exceptions are for.

You're making assertions here (pardon the pun) that totally miss the point. An assertion is a contract enforcement. Failure to meet the contract should result in failure. In the code above you would, one might hope, document that your sqrt function is happy to receive -ve values, in which case sqrt will throw an IntException. Given that, throwing the exception is valid. If I was writing it, I would have it as part of sqrt's precondition that x>=0. Thus, if x < 0, I would issue an assertion (in the broad sense of the term, not necessarily do assert()), and the process would halt. So, your assertion that "An assert is DEFINITELY not the right thing here" is only correct if you stipulate that -ve values are valid wrt to the contract for sqrt. If that's not the case, then it's just hot air, and your shouting is crass.
 And it will only halt the program if the exception is not caught. (Which is

 enough, I think). Anyone canny enough to wrap such calls in a try block can do
 their own tidy-up. And if they don't they'll get a nice error message.

And imagine all the nice extra code doing all this defensive programming. Yummy! I can only recommend you read Meyers book. A strong indication of the quality of the work is the degree to which it has influenced Walter's thinking (something notoriously difficult to do) despite the fact that he slags Walter off in Chapter 14.
 On the other hand, the Int class also supplies some LOW LEVEL functions. Here's
 one:

 #    uint bigintLLAdd(uint* d, uint* x, uint xLen, uint* y, uint yLen)
 #    in
 #    {
 #        assert(xLen >= yLen);
 #    }

 whereby the input MUST obey (xLen >= yLen), and if it doesn't then it's a bug

 the part of the caller. The assert tells whoever wrote the calling function to
 fix /their/ bug. This sort of thing I only ever do on seriously low level code,
 at the pointer and buffer level, where undefined behavior is the guaranteed
 result of naff input. As Norbert (I think) said, an "in" condition is part of
 the function's interface.

 So what do YOU think is the correct thing to do then, in both of these
 circumstances? And when exactly would you throw an exception?

I can't be bothered to plough through all the shouting in the second one, but I can tell you I'd make the function conform to its contract.
 Note that the phrase "exceptional conditions, i.e failures" is nonsense, since
 "exceptional conditions" does NOT mean the same thing as "failures". (The Latin
 abbreviation i.e. stands for "id est", which means "that is", "that is to say",
 or "in other words"). They're called "Exceptions" because they happen in
 exceptional (that is, rare, uncommon) circumstances. They're not called
 "Failures", a word which means something completely different. Perhaps you

 clarify your meaning?

Jul 14 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
Firstly, I don't read Arcane Jills caps to be shouting but rather emphasis 
of key/important words. I use things like *this* to mean emphasis, Jill 
uses THIS, I can handle both.

Secondly, lets take a step back and look at this with a broader example..

Say I write a word processor, say I use your recls code to list files in a 
directory, say the user specifies a path, I don't check thier input, and 
call a fn in your API with an invalid parameter.

You API will assert, my app will terminate, the user will loose their 
work.

This is not a good outcome.

Should I have checked the parameter I passed to you? Perhaps, that is one 
solution, assuming I did that, now my program checks the parameter, and 
then so does your API call, so we're checking something twice, what is the 
point of the seccond check?

Obviously the seccond check is required, your API needs to ensure it's 
input is not erroneous, so then I ask what is the point of the first check?

So we're back to not checking the input, but, we cannot have the app 
asserting and loosing the users work. *If* your assert was an exception I 
could catch it, give an error to the user and continue. The exception 
gives me the *user* of your API the choice.

I think I'll grab a copy of "Meyers book" what is it's title? (It must be 
here somewhere but I can't find it)

I typically only use asserts for internal functions/methods, ones that are 
*not* published in my API. To me asserts represent bugs/failures in my 
API, not in it's use.

Regan.

On Wed, 14 Jul 2004 21:47:06 +1000, Matthew 
<admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Arcane Jill" <Arcane_member pathlink.com> wrote in message
 news:cd35jt$1fll$1 digitaldaemon.com...
 In article <cd33r9$1cjn$1 digitaldaemon.com>, Arcane Jill says...
In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

I don't agree. Exceptions are for exceptional conditions, i.e 



errors. If you want to be "strict", then the right thing to do when a 


condition is violated is to halt. An exception is not the appropriate



Eh?

So what's wrong with this then? # Int sqrt(Int x) # { # if (x < 0) throw new IntException("sqrt(x) not defined for x < 0"); # //... # } An assert is DEFINITELY not the right thing here. The input could come from the intermediate result in a long calculation. Whether or not x is negative may not be deducable at compile time. So it's an error, and that's EXACTLY what exceptions are for.

You're making assertions here (pardon the pun) that totally miss the point. An assertion is a contract enforcement. Failure to meet the contract should result in failure. In the code above you would, one might hope, document that your sqrt function is happy to receive -ve values, in which case sqrt will throw an IntException. Given that, throwing the exception is valid. If I was writing it, I would have it as part of sqrt's precondition that x>=0. Thus, if x < 0, I would issue an assertion (in the broad sense of the term, not necessarily do assert()), and the process would halt. So, your assertion that "An assert is DEFINITELY not the right thing here" is only correct if you stipulate that -ve values are valid wrt to the contract for sqrt. If that's not the case, then it's just hot air, and your shouting is crass.
 And it will only halt the program if the exception is not caught. 
 (Which is

 enough, I think). Anyone canny enough to wrap such calls in a try block 
 can do
 their own tidy-up. And if they don't they'll get a nice error message.

And imagine all the nice extra code doing all this defensive programming. Yummy! I can only recommend you read Meyers book. A strong indication of the quality of the work is the degree to which it has influenced Walter's thinking (something notoriously difficult to do) despite the fact that he slags Walter off in Chapter 14.
 On the other hand, the Int class also supplies some LOW LEVEL 
 functions. Here's
 one:

 #    uint bigintLLAdd(uint* d, uint* x, uint xLen, uint* y, uint yLen)
 #    in
 #    {
 #        assert(xLen >= yLen);
 #    }

 whereby the input MUST obey (xLen >= yLen), and if it doesn't then it's 
 a bug

 the part of the caller. The assert tells whoever wrote the calling 
 function to
 fix /their/ bug. This sort of thing I only ever do on seriously low 
 level code,
 at the pointer and buffer level, where undefined behavior is the 
 guaranteed
 result of naff input. As Norbert (I think) said, an "in" condition is 
 part of
 the function's interface.

 So what do YOU think is the correct thing to do then, in both of these
 circumstances? And when exactly would you throw an exception?

I can't be bothered to plough through all the shouting in the second one, but I can tell you I'd make the function conform to its contract.
 Note that the phrase "exceptional conditions, i.e failures" is 
 nonsense, since
 "exceptional conditions" does NOT mean the same thing as "failures". 
 (The Latin
 abbreviation i.e. stands for "id est", which means "that is", "that is 
 to say",
 or "in other words"). They're called "Exceptions" because they happen in
 exceptional (that is, rare, uncommon) circumstances. They're not called
 "Failures", a word which means something completely different. Perhaps 
 you

 clarify your meaning?


-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 14 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message
news:opsa5ilho05a2sq9 digitalmars.com...
 Firstly, I don't read Arcane Jills caps to be shouting but rather emphasis
 of key/important words. I use things like *this* to mean emphasis, Jill
 uses THIS, I can handle both.

Ok. I understand that netiquette decreed - and I've been served many rebukes from C++ gliterrati who enjoy pointing out e-manners more than they like debating how many empty bases you can stuff onto the head of a pin - that _this is emphasis_ *this is a bit of a raised voice* THIS IS SHOUTING and, furthermore, that *this* may be interpreted as aggressive and THIS most certainly is aggresive. Oh well, hay ho!
 Secondly, lets take a step back and look at this with a broader example..

 Say I write a word processor, say I use your recls code to list files in a
 directory,

You cunning dog. You know a little flattery with recharge my battery. ;)
 say the user specifies a path, I don't check thier input, and
 call a fn in your API with an invalid parameter.

 You API will assert, my app will terminate, the user will loose their
 work.

Assuming you've passed in something that violates the pre-condition, yes. (Although, recls does not assert on invalid patterns or directories, it returns a status code indicating such. But let's assume for the sake of argument.)
 This is not a good outcome.

Agreed.
 Should I have checked the parameter I passed to you? Perhaps, that is one
 solution, assuming I did that, now my program checks the parameter, and
 then so does your API call, so we're checking something twice, what is the
 point of the seccond check?

[Meyer1997]: "Assertions are not an input checking mechanism" And I never use them as such. However, I need to qualify that. In STLSoft there are some assertions for pre-condition checking that masquerade as input validation. That's an aide d'discoverbilitae (apologies to any French speakers for my bastardisation). We have a similar thing in much of Phobos, where the in{} clause checks that something's not null. This is acceptable because both D and C/C++ have it as part of their culture that libraries may expect their clients to be correct. Were this not the case, then we're in the fat realm of the defensive programmer. In other words C/C++/D (can, they don't always do so) sacrifice DbC for release mode for the sake of efficiency. In and of itself, this does not negate the legitimacy of DbC, and all its ramifications. In practical terms, it simply means that the process will crash. Since a "caught" violation of a DbC contract is a halt, albeit one with some kind of message, the "uncaught" crash remains faithful to the cause. So, now that we've got that out of the way, we can look again at your concerns ...
 Obviously the seccond check is required, your API needs to ensure it's
 input is not erroneous, so then I ask what is the point of the first check?

One is user input validation, the other is contract enforcement. Consider the main entry function, Recls_Search() RECLS_FNDECL(recls_rc_t) Recls_Search( recls_char_t const *searchRoot , recls_char_t const *pattern , recls_uint32_t flags , hrecls_t *phSrch); Now, the contract for this function stipulates that it accepts NULL for searchRoot and for pattern. This means, respectively, to use the current directory, and to search for all files. Conversely, the contract stipulates that phSrch is *not* NULL. There is an assertion to that effect. Thus, if you pass a null pointer to Recls_Search, then you're going to get a halt, one way or another. In debug mode, you'll have a nice assertion and receive (since this is C/C++, not D) "Assertion failure: ...\recls_api.cpp(161): NULL != phSrch", or something similar. In release mode your halt will be less glamorous, since two lines later we have the statement "*phSrch = static_cast<hrecls_t>(0);" Now, one can certainly write defensively and test for phSrch. I used to do a lot more of that than I do now. Aside from the tedium, there are very good reasons why this is a "bad thing". Meyers goes through this in detail. For me there are three reasons. First it's more effort. Second you tend not to catch errors (by which I mean human coding errors, not exceptions) anywhere near as you might - your development time increases. Third, the locality of an error is lost, making tracking down a non-functioning application _far_ harder. I promise you that over the last few years when I've got less defensive, and more "aggresive", my coding time has dropped enormously, and application robustness has increased significantly.
 So we're back to not checking the input, but, we cannot have the app
 asserting and loosing the users work. *If* your assert was an exception I
 could catch it, give an error to the user and continue. The exception
 gives me the *user* of your API the choice.

 I think I'll grab a copy of "Meyers book" what is it's title? (It must be
 here somewhere but I can't find it)

"Object Oriented Software Construction" (Prentice-Hall) Be sure to write to him that it's a nice book, but you think Walter kicks his butt. ;)
 I typically only use asserts for internal functions/methods, ones that are
 *not* published in my API. To me asserts represent bugs/failures in my
 API, not in it's use.

 Regan.

 On Wed, 14 Jul 2004 21:47:06 +1000, Matthew
 <admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Arcane Jill" <Arcane_member pathlink.com> wrote in message
 news:cd35jt$1fll$1 digitaldaemon.com...
 In article <cd33r9$1cjn$1 digitaldaemon.com>, Arcane Jill says...
In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

I don't agree. Exceptions are for exceptional conditions, i.e



errors. If you want to be "strict", then the right thing to do when a


condition is violated is to halt. An exception is not the appropriate



Eh?

So what's wrong with this then? # Int sqrt(Int x) # { # if (x < 0) throw new IntException("sqrt(x) not defined for x < 0"); # //... # } An assert is DEFINITELY not the right thing here. The input could come from the intermediate result in a long calculation. Whether or not x is negative may not be deducable at compile time. So it's an error, and that's EXACTLY what exceptions are for.

You're making assertions here (pardon the pun) that totally miss the point. An assertion is a contract enforcement. Failure to meet the contract should result in failure. In the code above you would, one might hope, document that your sqrt function is happy to receive -ve values, in which case sqrt will throw an IntException. Given that, throwing the exception is valid. If I was writing it, I would have it as part of sqrt's precondition that x>=0. Thus, if x < 0, I would issue an assertion (in the broad sense of the term, not necessarily do assert()), and the process would halt. So, your assertion that "An assert is DEFINITELY not the right thing here" is only correct if you stipulate that -ve values are valid wrt to the contract for sqrt. If that's not the case, then it's just hot air, and your shouting is crass.
 And it will only halt the program if the exception is not caught.
 (Which is

 enough, I think). Anyone canny enough to wrap such calls in a try block
 can do
 their own tidy-up. And if they don't they'll get a nice error message.

And imagine all the nice extra code doing all this defensive programming. Yummy! I can only recommend you read Meyers book. A strong indication of the quality of the work is the degree to which it has influenced Walter's thinking (something notoriously difficult to do) despite the fact that he slags Walter off in Chapter 14.
 On the other hand, the Int class also supplies some LOW LEVEL
 functions. Here's
 one:

 #    uint bigintLLAdd(uint* d, uint* x, uint xLen, uint* y, uint yLen)
 #    in
 #    {
 #        assert(xLen >= yLen);
 #    }

 whereby the input MUST obey (xLen >= yLen), and if it doesn't then it's
 a bug

 the part of the caller. The assert tells whoever wrote the calling
 function to
 fix /their/ bug. This sort of thing I only ever do on seriously low
 level code,
 at the pointer and buffer level, where undefined behavior is the
 guaranteed
 result of naff input. As Norbert (I think) said, an "in" condition is
 part of
 the function's interface.

 So what do YOU think is the correct thing to do then, in both of these
 circumstances? And when exactly would you throw an exception?

I can't be bothered to plough through all the shouting in the second one, but I can tell you I'd make the function conform to its contract.
 Note that the phrase "exceptional conditions, i.e failures" is
 nonsense, since
 "exceptional conditions" does NOT mean the same thing as "failures".
 (The Latin
 abbreviation i.e. stands for "id est", which means "that is", "that is
 to say",
 or "in other words"). They're called "Exceptions" because they happen in
 exceptional (that is, rare, uncommon) circumstances. They're not called
 "Failures", a word which means something completely different. Perhaps
 you

 clarify your meaning?


-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/

Jul 14 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Thu, 15 Jul 2004 10:15:09 +1000, Matthew 
<admin stlsoft.dot.dot.dot.dot.org> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsa5ilho05a2sq9 digitalmars.com...
 Firstly, I don't read Arcane Jills caps to be shouting but rather 
 emphasis
 of key/important words. I use things like *this* to mean emphasis, Jill
 uses THIS, I can handle both.

Ok. I understand that netiquette decreed - and I've been served many rebukes from C++ gliterrati who enjoy pointing out e-manners more than they like debating how many empty bases you can stuff onto the head of a pin - that _this is emphasis_ *this is a bit of a raised voice* THIS IS SHOUTING and, furthermore, that *this* may be interpreted as aggressive and THIS most certainly is aggresive. Oh well, hay ho!

I find myself using both *this* and THIS to mean emphasis, I did not even know _this_ existed, you learn something new every day. I'll _try_ and change my habits :)
 Secondly, lets take a step back and look at this with a broader 
 example..

 Say I write a word processor, say I use your recls code to list files 
 in a
 directory,

You cunning dog. You know a little flattery with recharge my battery. ;)

:) It seemed as good an example as any other. To tell the truth I have not had cause to use it, yet.
 say the user specifies a path, I don't check thier input, and
 call a fn in your API with an invalid parameter.

 You API will assert, my app will terminate, the user will loose their
 work.

Assuming you've passed in something that violates the pre-condition, yes.

"invalid parameter" to me means "violates the pre-condition"
 (Although, recls does not assert on invalid patterns or directories, it 
 returns a
 status code indicating such. But let's assume for the sake of argument.)

 This is not a good outcome.

Agreed.

Funny how everyone agrees on the end result, just not how to get there.
 Should I have checked the parameter I passed to you? Perhaps, that is 
 one
 solution, assuming I did that, now my program checks the parameter, and
 then so does your API call, so we're checking something twice, what is 
 the
 point of the seccond check?

[Meyer1997]: "Assertions are not an input checking mechanism" And I never use them as such. However, I need to qualify that. In STLSoft there are some assertions for pre-condition checking that masquerade as input validation. That's an aide d'discoverbilitae (apologies to any French speakers for my bastardisation). We have a similar thing in much of Phobos, where the in{} clause checks that something's not null. This is acceptable because both D and C/C++ have it as part of their culture that libraries may expect their clients to be correct.

That does not make it 'good' only 'consistent'.
 Were this
 not the case, then we're in the fat realm of the defensive programmer.

I was once told to program my APIs as if my input was from a 'half sane monkey on crack' I guess that makes me a defensive programmer.
 In other words C/C++/D (can, they don't always do so) sacrifice DbC for 
 release
 mode for the sake of efficiency.

I can understand that, however IMO you cannot possibly find/catch _all_ the bugs in debug mode/testing. So some will creep thru into the relase build. Who cares how fast it runs if it's gonna crash? Your program will simply crash faster.
 In and of itself, this does not negate the
 legitimacy of DbC, and all its ramifications. In practical terms, it 
 simply means
 that the process will crash. Since a "caught" violation of a DbC 
 contract is a
 halt, albeit one with some kind of message, the "uncaught" crash remains 
 faithful
 to the cause.

I don't think I like this cause, it casues: - me to rely on the OS for a backtrace to find my bugs - the user to loose thier work. An exception solves the above problems.
 So, now that we've got that out of the way, we can look again at your 
 concerns
 ...

 Obviously the seccond check is required, your API needs to ensure it's
 input is not erroneous, so then I ask what is the point of the first 
 check?

One is user input validation, the other is contract enforcement.

I think your "contract enforcement" is simply another way of saying "input checking" which would mean you were breaking Meyers rule: "Assertions are not an input checking mechanism" Perhaps the above rule when it refers to 'input' is referring to 'end user' input? Using your example below, in _most_ cases the phSrch parameter will _not_ be affected by user input, meaning, so long as the developer passes one they'll never see the assert. And if they fail to pass one they'll see the assert once causing them to pass one in future. However, if it were affected by user input then you would not want an assert, you'd want an exception. I could dream up some buggy code where this is the case but I believe you can imagine it too. So whether you want to assert or throw an exception is based on the program calling your API, your API cannot possibly make this choice. By using an assert here, you're either: - achieving nothing (the developer never sees it, or sees it once) - causing problems (the app terminates the user loose their work) Given that, API input _must_ be treated as end user input and thus you cannot use assertions.
 Consider the
 main entry function, Recls_Search()

 RECLS_FNDECL(recls_rc_t) Recls_Search(  recls_char_t const  *searchRoot
                                     ,   recls_char_t const  *pattern
                                     ,   recls_uint32_t      flags
                                     ,   hrecls_t            *phSrch);

 Now, the contract for this function stipulates that it accepts NULL for
 searchRoot and for pattern. This means, respectively, to use the current
 directory, and to search for all files.

 Conversely, the contract stipulates that phSrch is *not* NULL. There is 
 an
 assertion to that effect.

It could be a InvalidParameterException instead.
 Thus, if you pass a null pointer to Recls_Search, then you're going to 
 get a
 halt, one way or another. In debug mode, you'll have a nice assertion 
 and receive
 (since this is C/C++, not D) "Assertion failure: ...\recls_api.cpp(161): 
 NULL !=
 phSrch", or something similar. In release mode your halt will be less 
 glamorous,
 since two lines later we have the statement "*phSrch = 
 static_cast<hrecls_t>(0);"

If it was an exception you could get it in both debug and release modes. You would not get a crash. The user would not loose their work.
 Now, one can certainly write defensively and test for phSrch. I used to 
 do a lot
 more of that than I do now. Aside from the tedium, there are very good 
 reasons
 why this is a "bad thing". Meyers goes through this in detail. For me 
 there are
 three reasons. First it's more effort.

Nothing is free, stability costs development time and effort.
 Second you tend not to catch errors (by
 which I mean human coding errors, not exceptions) anywhere near as you 
 might -
 your development time increases.

An exception will still catch human coding errors. Their development time will not change. Yours wont either, you just code "throw.." instead of "assert(.."
 Third, the locality of an error is lost, making
 tracking down a non-functioning application _far_ harder.

Why? Assuming exceptions have access to __FILE__ and __LINE__ (or their D equivalent) then you get just as much from them as an assert. This is the change I think we _need_. If __FILE__ and __LINE__ are only available in debug mode (which seems likely) an exception is still better than an assert as you can place any text you want in one. I know, this is what you're asking to be added to asserts, to me that suggests you want to use an exception instead.
 I promise you that over
 the last few years when I've got less defensive, and more "aggresive", 
 my coding
 time has dropped enormously, and application robustness has increased
 significantly.

I cannot confirm or deny that. ;) Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 14 2004
parent "Bent Rasmussen" <exo bent-rasmussen.info> writes:
 Perhaps the above rule when it refers to 'input' is referring to 'end
 user' input?

That what it refers to. Its not input from some function that is part of your program/system -- contracts works to make them correct, its input from some human or from outside the system where no correctness can be assumed -- you can't debug a human into allways inputting a correct e-mail address. :-) You can't ever assume "my users will input a correct e-mail address." So, the rule is - "defensive" for user-module messages (forms, files, etc.) - "offensive" for inter-module messages My guess is that a contract syntax motivates setting up traps against coding errors more than using exceptions do. Not that exceptions don't have their place. Its also nice to read a specification with concise and precise contracts. I can also recommend Object-Oriented Software Construction, its a great book; and also looking at EiffelSoft code for examples of contracts. In fact, some weeks ago I stumbled upon this link which may be a good introduction to contracts http://www.eiffel.com/developers/presentations/
Jul 15 2004
prev sibling next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Arcane Jill wrote:

In article <cd33r9$1cjn$1 digitaldaemon.com>, Arcane Jill says...
  

In article <cd2rij$tra$1 digitaldaemon.com>, Matthew says...

    

I don't agree. Exceptions are for exceptional conditions, i.e failures, not
human
errors. If you want to be "strict", then the right thing to do when a DbC
condition is violated is to halt. An exception is not the appropriate response.
      


So what's wrong with this then? # Int sqrt(Int x) # { # if (x < 0) throw new IntException("sqrt(x) not defined for x < 0"); # //... # } An assert is DEFINITELY not the right thing here. The input could come from the intermediate result in a long calculation. Whether or not x is negative may not be deducable at compile time. So it's an error, and that's EXACTLY what exceptions are for.

For a small function like sqrt, you don't want the extra overhead of exceptions in a release versions of the code. It really is an error on the caller, its not the sqrts fault that such a value was passed in. Assertions are about contracts, making sure the pre and post conditions are correct. Exceptions are about handling errors that arise in the code that you may not be there to fix when they occur. -- -Anderson: http://badmama.com.au/~anderson/
Jul 14 2004
prev sibling parent reply "Bent Rasmussen" <exo bent-rasmussen.info> writes:
 So what's wrong with this then?

 #    Int sqrt(Int x)
 #    {
 #        if (x < 0) throw new IntException("sqrt(x) not defined for x <

 #        //...
 #    }

I interpret assertions as a subtyping mechanism. E.g. the expression x >= 0 is an implicit construction of the type "natural", on a conceptual level. Its not as safe as compile time checking but useful nonetheless. It seems appropriate to use an assertion here. Defensive programming still has its place and probably beyond input validation for critical systems; no experience there though. :-) I don't know though, if it is possible to catch an assertion violation as an exception. That appears to be useful to me. Then if an assertion violation is caught then the assertion would not be turned off in the release build. But since assertions have no labels in D, it wouldn't be possible to catch a particular assertion violation, e.g. as in sqrt(Int x): Int require natural: x >= x.Zero Just a thought...
Jul 15 2004
parent reply "Carlos Santander B." <carlos8294 msn.com> writes:
"Bent Rasmussen" <exo bent-rasmussen.info> escribió en el mensaje
news:cd6nm7$2ddq$1 digitaldaemon.com
| I interpret assertions as a subtyping mechanism. E.g. the expression
|
|     x >= 0
|
| is an implicit construction of the type "natural", on a conceptual level.
| Its not as safe as compile time checking but useful nonetheless.
|

read below

| It seems appropriate to use an assertion here. Defensive programming still
| has its place and probably beyond input validation for critical systems;
no
| experience there though. :-)
|
| I don't know though, if it is possible to catch an assertion violation as
an
| exception. That appears to be useful to me. Then if an assertion violation
| is caught then the assertion would not be turned off in the release build.
| But since assertions have no labels in D, it wouldn't be possible to catch
a
| particular assertion violation, e.g. as in
|
|     sqrt(Int x): Int
|         require
|             natural: x >= x.Zero
|
| Just a thought...

It'd be better (and easier for the programmers) if D had ranges. Then you
would declare your own natural type with that condition. And it'd be compile
time.

-----------------------
Carlos Santander Bernal
Jul 15 2004
next sibling parent "Bent Rasmussen" <exo bent-rasmussen.info> writes:
 It'd be better (and easier for the programmers) if D had ranges. Then you
 would declare your own natural type with that condition. And it'd be

 time.

It would indeed. That's one of the things I liked when I saw some Pascal code awhile ago. It probably wouldn't extend well beyond primitive types though.
Jul 15 2004
prev sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Carlos Santander B. wrote:

"Bent Rasmussen" <exo bent-rasmussen.info> escribió en el mensaje
news:cd6nm7$2ddq$1 digitaldaemon.com
| I interpret assertions as a subtyping mechanism. E.g. the expression
|
|     x >= 0
|
| is an implicit construction of the type "natural", on a conceptual level.
| Its not as safe as compile time checking but useful nonetheless.
|

read below

| It seems appropriate to use an assertion here. Defensive programming still
| has its place and probably beyond input validation for critical systems;
no
| experience there though. :-)
|
| I don't know though, if it is possible to catch an assertion violation as
an
| exception. That appears to be useful to me. Then if an assertion violation
| is caught then the assertion would not be turned off in the release build.
| But since assertions have no labels in D, it wouldn't be possible to catch
a
| particular assertion violation, e.g. as in
|
|     sqrt(Int x): Int
|         require
|             natural: x >= x.Zero
|
| Just a thought...

It'd be better (and easier for the programmers) if D had ranges. Then you
would declare your own natural type with that condition. And it'd be compile
time.

-----------------------
Carlos Santander Bernal


  

-- -Anderson: http://badmama.com.au/~anderson/
Jul 16 2004
prev sibling parent Richard Krehbiel <rich kastle.com> writes:
Matthew Wilson wrote:
 Can I register yet another request for this long-looked-for feature?
 
 I'm finding it rather painful that the output just prints "Error:
 AssertError Failure vector(390)". It's just a PITA.
 
 Can we get this for 1.0?
 
 

#define ASSERT(x) if(!(x)) __assert_fail("Assertion failed: " ~ #x); And then, pass your D source thru your favorite C preprocessor first. (You don't have to avoid CPP. There's nothing wrong with it.)
Jul 16 2004