www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Where did my contracts go?

reply AJG <AJG_member pathlink.com> writes:
Hi,

First, I was happily coding in D under -debug. Then, I started using std.boxer
which requires that I use -release because of unresolved linking.

So I add -release (in _addition_ to -debug) and all hell breaks lose.

1) asserts no longer display anything meaningful; they segfault.
2) pre-condition (in) contracts disappear altogether.

What's going on? This seems extremely unreasonable to me.

I understand that some crazy people don't like safety contracts in their
-release code, but I specified -debug too.

Would it be possible to restore these 2 contracts, properly (no segfault), at
least under -debug? Please? I'm on linux w/ 129.

Thank you,
--AJG.
Aug 15 2005
next sibling parent reply "Charles" <noone nowhere.com> writes:
I agree , I think contracts should be completely seperate from 'release' and
'debug'.   Looking at the front end ( mars.c : 385 ) , it wouldn't take much
at all , just an extra command line argument , -contracts or some such.

This has been talked about before , not sure what the outcome was.

Charlie

P.S. Also , in the source it has useAssert parameter set to true if
unittests are on , maybe try that ?

"AJG" <AJG_member pathlink.com> wrote in message
news:ddqhqm$19a3$1 digitaldaemon.com...
 Hi,

 First, I was happily coding in D under -debug. Then, I started using

 which requires that I use -release because of unresolved linking.

 So I add -release (in _addition_ to -debug) and all hell breaks lose.

 1) asserts no longer display anything meaningful; they segfault.
 2) pre-condition (in) contracts disappear altogether.

 What's going on? This seems extremely unreasonable to me.

 I understand that some crazy people don't like safety contracts in their
 -release code, but I specified -debug too.

 Would it be possible to restore these 2 contracts, properly (no segfault),

 least under -debug? Please? I'm on linux w/ 129.

 Thank you,
 --AJG.

Aug 15 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi,

I agree , I think contracts should be completely seperate from 'release' and
'debug'.   Looking at the front end ( mars.c : 385 ) , it wouldn't take much
at all , just an extra command line argument , -contracts or some such.

I'm glad someone agrees. Another pro-safety feller I see ;) Indeed, a -contract argument would work well. Contracts should _always_ be enforced IMO. But I understand this isn't likely to happen. So, at least the choice to enforce them should be given independent of debug/release. For the tuning/tweaking crowd, a more fine-grained version could be offered: -contracts // all -contracts:in // preconditions -contracts:assert // asserts etc.
This has been talked about before , not sure what the outcome was.

Walter?
Charlie

P.S. Also , in the source it has useAssert parameter set to true if
unittests are on , maybe try that ?

Not sure what you mean. Which source? Cheers, --AJG.
Aug 15 2005
parent "Charles" <noone nowhere.com> writes:
 For the tuning/tweaking crowd, a more fine-grained version could be

Yes even better :).
 Not sure what you mean. Which source?

Sorry the mars.c:385 frontend , it seems to turn on asserts when -unittest is given , though I haven't tried it or anything. Charlie "AJG" <AJG_member pathlink.com> wrote in message news:ddrp8i$28b5$1 digitaldaemon.com...
 Hi,

I agree , I think contracts should be completely seperate from 'release'


'debug'.   Looking at the front end ( mars.c : 385 ) , it wouldn't take


at all , just an extra command line argument , -contracts or some such.

I'm glad someone agrees. Another pro-safety feller I see ;) Indeed, a -contract argument would work well. Contracts should _always_ be enforced IMO. But I understand this isn't likely to happen. So, at least

 choice to enforce them should be given independent of debug/release.

 For the tuning/tweaking crowd, a more fine-grained version could be

 -contracts // all
 -contracts:in // preconditions
 -contracts:assert // asserts
 etc.

This has been talked about before , not sure what the outcome was.

Walter?
Charlie

P.S. Also , in the source it has useAssert parameter set to true if
unittests are on , maybe try that ?

Not sure what you mean. Which source? Cheers, --AJG.

Aug 16 2005
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"AJG" <AJG_member pathlink.com> wrote in message 
news:ddqhqm$19a3$1 digitaldaemon.com...
 Hi,

 First, I was happily coding in D under -debug. Then, I started using 
 std.boxer
 which requires that I use -release because of unresolved linking.

 So I add -release (in _addition_ to -debug) and all hell breaks lose.

 1) asserts no longer display anything meaningful; they segfault.
 2) pre-condition (in) contracts disappear altogether.

 What's going on? This seems extremely unreasonable to me.

 I understand that some crazy people don't like safety contracts in their
 -release code, but I specified -debug too.

 Would it be possible to restore these 2 contracts, properly (no segfault), 
 at
 least under -debug? Please? I'm on linux w/ 129.

 Thank you,
 --AJG.

If you want to use boxer in a module with asserts turned on you have to recompile phobos with asserts turned on (ie without -release). Edit the makfile in dmd/src/phobos to uncomment the unittest DFLAGS variable and run make.
Aug 15 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi,

If you want to use boxer in a module with asserts turned on you have to 
recompile phobos with asserts turned on (ie without -release). Edit the 
makfile in dmd/src/phobos to uncomment the unittest DFLAGS variable and run 
make. 

While this helps with std.boxer specifically, it doesn't help with contracts in general. Before anything, are the following three things clearly defined anywhere? A) -debug B) -release C) -debug -release D) -release -debug (if different from C). In addition, I'm really surprised (read: annoyed) that release/debug have an effect on contracts. This is faulty logic IMHO. It would make more sense to do the following: # void Foo(int a) in { # assert(a == 42); // Stays there forever. # debug assert(someExpensiveCheck(a)); // Removed in release. # } body { /* body */ } Or perhaps, something like: # void Foo(int a) debug in { // All removed in release. # assert(a == 42); # assert(someExpensiveCheck(a)); # } body { /* body */ } Thanks, --AJG.
Aug 15 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 15 Aug 2005 20:18:48 +0000 (UTC), AJG wrote:

 Hi,
 
If you want to use boxer in a module with asserts turned on you have to 
recompile phobos with asserts turned on (ie without -release). Edit the 
makfile in dmd/src/phobos to uncomment the unittest DFLAGS variable and run 
make. 

While this helps with std.boxer specifically, it doesn't help with contracts in general. Before anything, are the following three things clearly defined anywhere?

Yes. In the documentation for the DMD compiler and the documentation for conditional compilation.
 A) -debug

compile in debug code -debug=level compile in debug code <= level -debug=ident compile in debug code identified by ident
 B) -release

compile release version, which means not generating code for contracts and asserts
 C) -debug -release

 D) -release -debug (if different from C).

"-release" and "-debug" are totally independent from each other.
 In addition, I'm really surprised (read: annoyed) that release/debug have an
 effect on contracts. This is faulty logic IMHO.

"-debug" does not effect contracts at all. Only "-release" does.
 It would make more sense to do the following:
 
 # void Foo(int a) in {
 #     assert(a == 42); // Stays there forever.

 #     debug assert(someExpensiveCheck(a)); // Removed in release.
 # } body { /* body */ }

You are encouraged to code such a 'contract' in this manner instead ... void Foo(int a) in { assert(someExpensiveCheck(a)); // Removed in release. } body { // Input *data* validation. if (a == 42) Abend("In Foo(), the input data must be 42"); /* rest of body */ } -- Derek Parnell Melbourne, Australia 16/08/2005 7:35:23 AM
Aug 15 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi Derek,

Before anything, are the following three things clearly defined
 anywhere?

Yes. In the documentation for the DMD compiler and the documentation for conditional compilation.

Well, I must be reading something wrong, cause... ~test.d: # void main() { # printf("Before\n"); # assert(false); # printf("After\n"); # }
 A) -debug

compile in debug code -debug=level compile in debug code <= level -debug=ident compile in debug code identified by ident

This is fine. Debug seems to work properly. Output: # Before # Error: AssertError Failure test.d(3)
 B) -release

compile release version, which means not generating code for contracts and asserts

Not quite... Output: # Before # Segmentation Fault
 C) -debug -release

 D) -release -debug (if different from C).


Once again, the output is: # Before # Segmentation Fault
"-release" and "-debug" are totally independent from each other.

Well, sort of. What about when you don't specify _either_ one? The it is assumed you meant -debug, right? Well, then that means there is no way to _explicitly_ set NO-debug, other than to say -release. That means, thus, that they are related.
 In addition, I'm really surprised (read: annoyed) that release/debug have an
 effect on contracts. This is faulty logic IMHO.


Doesn't seem to be that way. -release makes asserts segfault.
 It would make more sense to do the following:
 
 # void Foo(int a) in {
 #     assert(a == 42); // Stays there forever.


It's _not_ about the user. It's about basic function safety. Why have a section called "in," where you are supposed to check for pre-conditions, when that section is effectively _useless_ in real code? This is a bad design decision, IMHO. Asserts are a simple and elegant way to prevent bizarre and potentially catastrophic behaviour that you don't expect to happen in real code, but just _might_. When debugging, they are useful tools to the programmer. But they are doubly useful: In real code, they are last-resort, emergency guards. Well, you say, throw an exception. You want me to instead throw an exception every time I have an assert? The sheer verbosity will kill you. For every: assert(c); You must use: if (!c) throw new Exception("Error: AssertError Failure ajg.module.d(13)"); Look at that monster. If you pepper your code with Exceptions where regular asserts would have sufficed, you are looking at some serious code bloat. Just like const, the meaning is lost in all that pomposity and syntax. Assert, on the other hand is concise and elegant. Therefore, I use asserts a lot, because I would want my code to be bulletproof. Moreover, there are even more disadvantages: 1) It's a heck of a lot more work. You are less likely to do it. 2) You lose automatic module/line-number indications. 3) It's a more complex construct. 4) Thus, you lose the immediate, quick, straight-forward meaning. An assert is a simple guard. You see it an you know that condition must never happen. OTOH, an exception is a much more powerful error-handling facility. When I put an assert, I don't want to handle an error, I want execution to come to a screeching halt lest the situation get even worse. Well, use a _function_ that throws an exception, you say. I suppose that's what your "Abend" function does, right? First off, still quite verbose: # // Assuming this: # void assert2(int c, string m) { # if (!c) throw new Exception("Error: AssertError Failure " ~ m); # } assert(c); vs. assert2(c, "ajg.module.d(13)"); Even more problems: 1) It's a lot more work. Harder to maintain. 2) Still no automatic module/line-number. 3) Even worse, now the exception will seem to originate in a completely different, generic place. Bad! 4) The compiler has no knowlege of the fact that the function is a special one, designed specifically to throw. So it can't detect dead code. It also can't "know" what you mean when you say assert(false). 5) Replacing a built-in _language_ facility with a hack is just ridiculous. That's why there is assert() in the first place.
You are encouraged to code such a 'contract' in this manner instead ...
 void Foo(int a) 
 in {
    assert(someExpensiveCheck(a)); // Removed in release.
 } 
 body { 
    // Input *data* validation.
    if (a == 42) Abend("In Foo(), the input data must be 42");
    /* rest of body */ 
 }

Two things: 1) Once again, it's not only about user-input validation. It's about validation of preconditions in general. These can, for example, be parameters that can come from anywhere. They can come directly from the end user, or from another programmer, or from a corrupted stack, or from god knows where. But it doesn't even have to be parameters. It can be any sort of precondition. Having enough memory. A thread having stopped. A variable having been set. A mutex having been released. Anything. It makes sense to put these things in a section called "in," which is specifically designed to check for pre-conditions. You mean to say all these things magically dissapear in production code? If that's the "philosophy," then that's quite dangerous and naive. It's exactly the _other_ way around, these things become more likely to happen (uncontrolled, distinct environment(s)) and much more likely to be seriously harmful (real, important data/systems at stake). 2) Also, why bother having an "in" section in the first place? This just creates a mess. You must split your "real" checks from the fake ones into two sections, when the "in" one could nicely handle both. This split would be fine for one function, but not for all. It's very distracting. Cheers, --AJG (linux w/ 129). PS: As you can tell, I am pro-assert, and pro-in. In other words, pro-safety. You must always practice safe hex, people! ;)
Aug 15 2005
parent Derek Parnell <derek psych.ward> writes:
On Tue, 16 Aug 2005 04:03:59 +0000 (UTC), AJG wrote:

 Hi Derek,
 
Before anything, are the following three things clearly defined
 anywhere?

Yes. In the documentation for the DMD compiler and the documentation for conditional compilation.

Well, I must be reading something wrong, cause... ~test.d: # void main() { # printf("Before\n"); # assert(false); # printf("After\n"); # }
 A) -debug

compile in debug code -debug=level compile in debug code <= level -debug=ident compile in debug code identified by ident

This is fine. Debug seems to work properly. Output: # Before # Error: AssertError Failure test.d(3)

 B) -release

compile release version, which means not generating code for contracts and asserts

Not quite... Output: # Before # Segmentation Fault

According to the documentation (see 'Expressions')... " The expression assert(0) is a special case; it signifies that it is unreachable code. Either AssertError is thrown at runtime if it is reachable, or a HLT instruction is executed. The optimization and code generation phases of compilation may assume that it is unreachable code. " What the docs do not make clear is that this special case assert is not totally removed by "-release" switch. Maybe it should ... maybe not? I don't know. However I do know that if you place a more typical assert there then the -release switch does remove it. [snip]
 
 It would make more sense to do the following:
 
 # void Foo(int a) in {
 #     assert(a == 42); // Stays there forever.


It's _not_ about the user. It's about basic function safety.

I must disagree here - it *is* about the user. Why are we writing programs if they are not meant to be used? We, as developers, must help the user by delivering correct algorithms (our logic) using the correct information (data from user). Function safety must check for at least two areas of concern: a) the algorithm is correct; b) the data it is working with is correct. Given (and I repeat, *given*) the current implementation of assert, which only gives file and line number info, how is that useful to an end-user? Sure its useful stuff to the development team, but how does it really make end-users feel warm and fuzzy? The current assert implementation is designed to help developers detect *logic* problems. It is not designed to help us detect *data* problems. Sure it uses data to test, but the data is expected to come from the results of your logic, not stuff that is supplied by a user. I'm not saying that this is how the world ought ot operate, just that this is how D operates. I'm not saying that Walter has got it right or wrong, just was exists in D. So starting from that position, do not use asserts to validate function arguments, instead use assert to validate function results.
 Why have a section
 called "in," where you are supposed to check for pre-conditions, when that
 section is effectively _useless_ in real code? This is a bad design decision,
 IMHO.

I agree that the way in{} is implemented makes it useless in all but the rarest of situations. I can't think of any reason to use it the way it currently is.
 Asserts are a simple and elegant way to prevent bizarre and potentially
 catastrophic behaviour that you don't expect to happen in real code, but just
 _might_. 

But not D asserts(). May be you are right about the assert() as implemented in other languages. The basic premise of the assert concept is that it tests data and aborts the program if the test fails. The question that we are now dealing with is where does that data come from? If it comes from function arguments, then the D assert is useless code.
When debugging, they are useful tools to the programmer. But they are
 doubly useful: In real code, they are last-resort, emergency guards.

This is a matter of opinion, because there are ways to validate data other than using the assert construct.
 Well, you say, throw an exception. You want me to instead throw an exception
 every time I have an assert? The sheer verbosity will kill you. For every:
 
 assert(c);
 
 You must use:
 
 if (!c) throw new Exception("Error: AssertError Failure ajg.module.d(13)");

 Look at that monster. If you pepper your code with Exceptions where regular
 asserts would have sufficed, you are looking at some serious code bloat. Just
 like const, the meaning is lost in all that pomposity and syntax. Assert, on
the
 other hand is concise and elegant. Therefore, I use asserts a lot, because I
 would want my code to be bulletproof.

In that case, ship an edition of your application that was not compiled with "-release". The choice is yours. No one is forcing you to use "-release".
 Moreover, there are even more disadvantages:
 
 1) It's a heck of a lot more work. You are less likely to do it.
 2) You lose automatic module/line-number indications.
 3) It's a more complex construct.
 4) Thus, you lose the immediate, quick, straight-forward meaning. An assert is
a
 simple guard. You see it an you know that condition must never happen. 
 
 OTOH, an exception is a much more powerful error-handling facility. When I put
 an assert, I don't want to handle an error, I want execution to come to a
 screeching halt lest the situation get even worse.

assert(0) ???
 Well, use a _function_ that throws an exception, you say. I suppose that's what
 your "Abend" function does, right? First off, still quite verbose:
 
 # // Assuming this:
 # void assert2(int c, string m) { 
 #     if (!c) throw new Exception("Error: AssertError Failure " ~ m); 
 # }
 
 assert(c);
 vs.
 assert2(c, "ajg.module.d(13)");
 
 Even more problems:
 
 1) It's a lot more work. Harder to maintain.
 2) Still no automatic module/line-number.
 3) Even worse, now the exception will seem to originate in a completely
 different, generic place. Bad!
 4) The compiler has no knowlege of the fact that the function is a special one,
 designed specifically to throw. So it can't detect dead code. It also can't
 "know" what you mean when you say assert(false).
 5) Replacing a built-in _language_ facility with a hack is just ridiculous.
 That's why there is assert() in the first place.
 
You are encouraged to code such a 'contract' in this manner instead ...
 void Foo(int a) 
 in {
    assert(someExpensiveCheck(a)); // Removed in release.
 } 
 body { 
    // Input *data* validation.
    if (a == 42) Abend("In Foo(), the input data must be 42");
    /* rest of body */ 
 }

Two things: 1) Once again, it's not only about user-input validation. It's about validation of preconditions in general. These can, for example, be parameters that can come from anywhere. They can come directly from the end user, or from another programmer, or from a corrupted stack, or from god knows where. But it doesn't even have to be parameters. It can be any sort of precondition. Having enough memory. A thread having stopped. A variable having been set. A mutex having been released. Anything. It makes sense to put these things in a section called "in," which is specifically designed to check for pre-conditions. You mean to say all these things magically dissapear in production code? If that's the "philosophy," then that's quite dangerous and naive. It's exactly the _other_ way around, these things become more likely to happen (uncontrolled, distinct environment(s)) and much more likely to be seriously harmful (real, important data/systems at stake).

I agree that it is important to validate pre-conditions. D gives you two ways of doing it, and you can do both simultaneously. One is to do checking inside of in{} blocks which only occur in pre-release code, and the other is to do the checking in body{} blocks which can occur in both pre-release and release code. If you specifically want checks done using assert then you must release 'pre-release' code. If you want these checks done in "-release" code then do not use asserts. I'm sorry that it is more cumbersome when not using asserts, but that's what's been implemented.
 2) Also, why bother having an "in" section in the first place? This just
creates
 a mess. You must split your "real" checks from the fake ones into two sections,
 when the "in" one could nicely handle both. This split would be fine for one
 function, but not for all. It's very distracting.

Totally agree.
 PS: As you can tell, I am pro-assert, and pro-in. In other words, pro-safety.
 You must always practice safe hex, people! ;)

I'm also pro-safety, thus I don't use assert() and in{} blocks to validate function parameters (or other environmental dependencies); I use different techniques. -- Derek (skype: derek.j.parnell) Melbourne, Australia 16/08/2005 2:15:52 PM
Aug 15 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 15 Aug 2005 17:02:14 +0000 (UTC), AJG wrote:

 Hi,
 
 First, I was happily coding in D under -debug. Then, I started using std.boxer
 which requires that I use -release because of unresolved linking.
 
 So I add -release (in _addition_ to -debug) and all hell breaks lose.
 
 1) asserts no longer display anything meaningful; they segfault.
 2) pre-condition (in) contracts disappear altogether.
 
 What's going on? This seems extremely unreasonable to me.
 
 I understand that some crazy people don't like safety contracts in their
 -release code, but I specified -debug too.
 
 Would it be possible to restore these 2 contracts, properly (no segfault), at
 least under -debug? Please? I'm on linux w/ 129.

Believe it or not, but this is a philosophical discussion. Walter's philosophy (and yes, I'm speculating here) is that the purpose of the in{} and out{} blocks and assert() calls is to alert the developer of any mistakes in their code logic. They are not to be used to detect bad data. The "-release" effects these constructs because by the time you create the production edition, all the code logic has been validated. This means that if you require that the end user is alerted to logic errors, your choices are that you supply them with a non-release edition and/or you code your 'contracts' outside of the in{}, out{}, and assert() constructs. The choice is yours. Further more, validation of user data should never be coded inside contract constructs as these are designed to detect *logic* mistakes and not data problems. In short, you are encouraged to detect logic errors before you get your application to an end user, and to detect data errors within all editions of your application. The "-debug" switch has got absolutely nothing to do with contracts whatsoever. The "-debug" switch has identical functionality to the "-version" switch. There can be considered as aliases for each other. However, the reason for using different words ('debug' vs 'version') is to emphasize the different purposes of the conditional code. Code that is conditionally compiled in with 'version' represents valid alternatives of the application based on environmental, platform, or usage variations. Those fragments of code conditionally compiled in with 'debug' represent valid alternatives for pre-production editions. By having both 'version' and 'debug', we can intermix there usage to create very precise editions of the application to suit all purposes. Yes, it is easy to confuse the debug() construct with contract programming, but in D they are not the same. It is especially important to realize that the "-release" switch has no effect on the debug() construct. The "-release" switch also removes the hidden asserts (range-checking, missing returns, etc...) as well as the explicit asserts. As the assert() call only displays information useful to people who have access to the source code, it is a bit pointless using asserts to alert end-users to problems. -- Derek Parnell Melbourne, Australia 16/08/2005 7:06:17 AM
Aug 15 2005
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Derek Parnell wrote:
 On Mon, 15 Aug 2005 17:02:14 +0000 (UTC), AJG wrote:
 
 
Hi,

First, I was happily coding in D under -debug. Then, I started using std.boxer
which requires that I use -release because of unresolved linking.

So I add -release (in _addition_ to -debug) and all hell breaks lose.

1) asserts no longer display anything meaningful; they segfault.
2) pre-condition (in) contracts disappear altogether.

What's going on? This seems extremely unreasonable to me.

I understand that some crazy people don't like safety contracts in their
-release code, but I specified -debug too.

Would it be possible to restore these 2 contracts, properly (no segfault), at
least under -debug? Please? I'm on linux w/ 129.

Believe it or not, but this is a philosophical discussion.

Why then does the overview page say: "D (...) doesn't come with (...) an overriding philosophy." http://www.digitalmars.com/d/overview.html and um, I think the word "philosophy" has different meanings in different context, and in the context of your post, it means "principle" or "idea".. so if we debate the meaning of "-release" it wouldn't really be a /philosophical/ discussion, because we're not debating the nature of time and space :P From answers.com: http://www.answers.com/philosophy&r=67 2. Investigation of the nature, causes, or principles of reality, knowledge, or values, based on logical reasoning rather than empirical methods. 7. A set of *ideas or beliefs* relating to a particular field or activity; an underlying theory: /an original philosophy of advertising/.
 
 Walter's philosophy (and yes, I'm speculating here) is that the purpose of
 the in{} and out{} blocks and assert() calls is to alert the developer of
 any mistakes in their code logic. They are not to be used to detect bad
 data. The "-release" effects these constructs because by the time you
 create the production edition, all the code logic has been validated.
 
 This means that if you require that the end user is alerted to logic
 errors, your choices are that you supply them with a non-release edition
 and/or you code your 'contracts' outside of the in{}, out{}, and assert()
 constructs. The choice is yours.
 
 Further more, validation of user data should never be coded inside contract
 constructs as these are designed to detect *logic* mistakes and not data
 problems. In short, you are encouraged to detect logic errors before you
 get your application to an end user, and to detect data errors within all
 editions of your application.
 
 The "-debug" switch has got absolutely nothing to do with contracts
 whatsoever. The "-debug" switch has identical functionality to the
 "-version" switch. There can be considered as aliases for each other.
 However, the reason for using different words ('debug' vs 'version') is to
 emphasize the different purposes of the conditional code. Code that is
 conditionally compiled in with 'version' represents valid alternatives of
 the application based on environmental, platform, or usage variations.
 Those fragments of code conditionally compiled in with 'debug' represent
 valid alternatives for pre-production editions. By having both 'version'
 and 'debug', we can intermix there usage to create very precise editions of
 the application to suit all purposes.
 
 Yes, it is easy to confuse the debug() construct with contract programming,
 but in D they are not the same. It is especially important to realize that
 the "-release" switch has no effect on the debug() construct.
 
 The "-release" switch also removes the hidden asserts (range-checking,
 missing returns, etc...) as well as the explicit asserts.
 
 As the assert() call only displays information useful to people who have
 access to the source code, it is a bit pointless using asserts to alert
 end-users to problems.
 

Aug 15 2005
parent Derek Parnell <derek psych.ward> writes:
On Mon, 15 Aug 2005 22:13:10 -0600, Hasan Aljudy wrote:

 Derek Parnell wrote:

[snip]
 
 Believe it or not, but this is a philosophical discussion.

Why then does the overview page say: "D (...) doesn't come with (...) an overriding philosophy." http://www.digitalmars.com/d/overview.html

I've often laughed at that usage. Walter's *philosophy* is liberally sprinkled throughout D.
 and um, I think the word "philosophy" has different meanings in 
 different context, and in the context of your post, it means "principle" 
 or "idea"..

Maybe ... but I was more leaning towards the meaning of "belief system". That is to say, it's what Walter believes how things ought to be. Other people could have an alternate belief system that clashes with Walter's one.
 so if we debate the meaning of "-release" it wouldn't really be a 
 /philosophical/ discussion, because we're not debating the nature of 
 time and space :P

Just the nature of 'Programming Done Well' ;-)
  From answers.com:
 http://www.answers.com/philosophy&r=67
 2. Investigation of the nature, causes, or principles of reality, 
 knowledge, or values, based on logical reasoning rather than empirical 
 methods.

Yep, this is also what I meant. Not much in Programming Practice has been empirically proven. Somethings sure e.g. "goto increases the cost of maintenance" but not everything (yet).
 7. A set of *ideas or beliefs* relating to a particular field or 
 activity; an underlying theory: /an original philosophy of advertising/.

Yes to this one too. -- Derek (skype: derek.j.parnell) Melbourne, Australia 16/08/2005 2:48:03 PM
Aug 15 2005
prev sibling parent reply AJG <AJG_member pathlink.com> writes:
Hi,

 Would it be possible to restore these 2 contracts, properly (no segfault), at
 least under -debug? Please? I'm on linux w/ 129.

Believe it or not, but this is a philosophical discussion.

This is all well and good, but D is supposed to be borne out of practice. The current "philosophy" as it were doesn't seem very pragmatic. See below.
Walter's philosophy (and yes, I'm speculating here) is that the purpose of
the in{} and out{} blocks and assert() calls is to alert the developer of
any mistakes in their code logic. They are not to be used to detect bad
data. The "-release" effects these constructs because by the time you
create the production edition, all the code logic has been validated.

Walter, could you confirm this? If it's true, this is not good news for safety.
This means that if you require that the end user is alerted to logic
errors, your choices are that you supply them with a non-release edition
and/or you code your 'contracts' outside of the in{}, out{}, and assert()
constructs. The choice is yours.

The only choice I see is between safe (debug) and unsafe(release). I understand if you want the marginal extra speed of the unsafe version, but perhaps this safety (aka contracts) could be made into a separate option? "Release" code should have nothing to do with contracts or safety. It should be about removing extra symbols, stripping useless sections, etc. Not safety. Not contracts. Well, IMHO, of course. Release is already sort-of indendent of debug. Fine. Couldn't it also be independent of contracts? This would solve a lot.
Further more, validation of user data should never be coded inside contract
constructs as these are designed to detect *logic* mistakes and not data
problems. In short, you are encouraged to detect logic errors before you
get your application to an end user, and to detect data errors within all
editions of your application.

Could I get a precise definition of a logic mistake vs. a "data" mistake, please? I would think the two are intertwined. Thus, there is only _one_ kind of error coming into a function: a pre-condition. Everything falls into that. The in block is _specifically_ stated to take care of pre-conditions. But it fails in -release. It leaves the code unprotected against unexpected failing pre-conditions. It's as simple as that: No pre-condition protection. No safety.
By having both 'version'
and 'debug', we can intermix there usage to create very precise editions of
the application to suit all purposes.

I don't see where you are getting all that "precision," since a single -release (even with -debug(s)) wipes out all in/out contracts and causes asserts to segfault. That's kind of un-precise. Rather, it's kind of blunt.
Yes, it is easy to confuse the debug() construct with contract programming,
but in D they are not the same. It is especially important to realize that
the "-release" switch has no effect on the debug() construct.

Yes, it's counter-intuitive. Traditionally, release and debug are mutually exclusive (as they should be), since they are contradicting terms. But not in D. Great. How is this a good thing?
The "-release" switch also removes the hidden asserts (range-checking,
missing returns, etc...) as well as the explicit asserts.

This is insane. So IndexOutOfBounds checks are _gone_ in release? So I guess arrays will _NEVER_ be overrun in production code, right? Because as we know, _all_ bugs are solved during the initial design. Yeah, good thinking.
As the assert() call only displays information useful to people who have
access to the source code, it is a bit pointless using asserts to alert
end-users to problems.

Uh... no. A human-readable line like: "Error: AssertError Failure ajg.module.d(13)" is: 1) A lot friendlier nasty segfault. 2) More understandable. 3) QUITE useful. The user could actually send this message to customer support, or when submitting a bug report, etc. The idea that asserts (or worse, contracts in general) are only useful to the immediate programmer is misguided. Cheers, --AJG.
Aug 15 2005
next sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
AJG wrote:

 The idea that asserts (or worse, contracts in general) are only useful to the
 immediate programmer is misguided.

The idea that asserts are to be used for anything other than development is misguided. I don't know your background, but the idea of compiling out asserts in release builds has been in practice in C and C++ for quite a long while. Assert is for validation of logic and *known* inputs (for example, validating that an arg is not null, or that an object was set to a specific state before the function was called), and not for unknown inputs (what Derek referred to as data - user input, scripted data, anything that isn't known at compile time). In C, whenever you need to validate unknown inputs you check it with an if block. Even Java has asserts now (since 1.4) because Java developers wanted something useful for development that could be compiled out at release (previously they had to if() everything). What you are trying to do is use assert in a manner that goes against its intended and standard use. It is not, in any language I know, meant for use in production code. Asserts are meant to be able to be compiled out, period. The confusing part here is DBC. I agree DBC would be useful in production code. The in blocks can be used to validate both known inputs (assert) and unknown inputs (if(!condition) throw)). As it stands in D, DBC implemented on the same grounds as assert - for development purposes and not for release builds. But even so, you can get the same functionality now with if blocks, which is a much better option than assert abuse. An if block says 'I am meant to be here in production code' where as an assert says 'I am meant to be compiled out in production code'. Just say 'No' to assert abuse!
Aug 15 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi,

AJG wrote:

 The idea that asserts (or worse, contracts in general) are only useful to the
 immediate programmer is misguided.

The idea that asserts are to be used for anything other than development is misguided. I don't know your background, but the idea of compiling out asserts in release builds has been in practice in C and C++ for quite a long while.

First off, D is not C, and D is not C++. D is supposed to be better than those two. C and C++, relatively speaking, are not safe languages. I hope that D would want to do better. But, I'm going to play the devil's advocate: On the linux side, I use GCC. GCC compiles asserts in by default. In fact, according to the C standard, asserts _should be in_ by default, so GCC is rightly following this convention. In order to remove asserts, you specifically have to FORCE the symbol NDEBUG into your code. The verb "force" is not mine, it's in the very spec: http://www.opengroup.org/onlinepubs/009695399/functions/assert.html So, when I compile "release" code, I do something like: gcc -Wall -Pedantic -O3 <code> Whereas you would evidently do: gcc -DNDEBUG (...) See, that's _your_ decision. Just because you think so doesn't mean you should FORCE it upon the world. Specially when it reduces the safety of a function. I don't call that release code, I call that unsafe code. Let's go over that one again: Removing asserts unequivocally reduces the safety of a function. Period. One last interesting bit is that even in -O3, the highest optimization level, asserts are _still_ left in the code (as they should) by the compiler. Therefore, asserts (and their safety) and optimization can be kept independent. On the windows side, I use VC++. VC++ does something wonderful in the form of VERIFY. It's a version of assert that never goes away. That's what I always use and I love it. Unfortunately, D doesn't have that. In fact, that would be a great compromise. If D were to introduce a permanent assert, e.g. verify(), then we could both have what we want.
 Assert is for validation of logic and *known* inputs 
(for example, validating that an arg is not null, or that an object was 
set to a specific state before the function was called), 

There is no such thing as a "known" input. Are you telling me you know, in advance, _every_, _single_ way your function is going to be called in the future? Every possibility? Every programmer? Every project and program? That seems a bit unlikely to me (Perhaps you are an oracle?). Therefore, it is unsafe. You don't know how and when your function is going to be called. Asserts are the guards that prevent bizarre calls from turning catastrophic. Leave them in! Or at least, let _me_ leave _mine_ in.
and not for 
unknown inputs (what Derek referred to as data - user input, scripted 
data, anything that isn't known at compile time).

Oh, so then a "known input" is, by your definition, known at compile time. That's great. So I guess your asserts look something like this: const int Foo = 42; assert(1 == 1); assert("car" == "car"); assert(Foo == 42); Right? Well, those "known inputs" go into static asserts, not regular asserts. They would be _trivial_ as regular asserts.
In C, whenever you 
need to validate unknown inputs you check it with an if block.

Maybe _you_ do that. That's verbose, more complex and less clear. OTOH, I use asserts for a lot of conditions that you might think will never happen, but, because of the nature of programs, you never know. Just out of curiosity, what do you use asserts for, then? It must be for some truly trivial stuff, if I understand you correctly. Otherwise, if _not_ trivial, it is _wiped out_ in -release and all that non-trivial checking goes out the window. Do you see my point? So which one is it, trivial asserts or useful asserts?
What you are trying to do is use assert in 
a manner that goes against its intended and standard use. It is not, in 
any language I know, meant for use in production code. Asserts are meant 
to be able to be compiled out, period.

Once again, that's your opinion. All I am asking is for the choice to be left to the programmer independent of the code being "production" or not. One solution is the -contracts argument. Another would be the verify() version that doesn't go away. Either one would be fine by me. Both would be even better.
The confusing part here is DBC. I agree DBC would be useful in 
production code. The in blocks can be used to validate both known inputs 
(assert) and unknown inputs (if(!condition) throw)). As it stands in D, 
DBC implemented on the same grounds as assert - for development purposes 
and not for release builds.

Agreed. DBC is good independent of "production" code as well. The -contracts argument would solve this problem.
But even so, you can get the same 
functionality now with if blocks, which is a much better option than 
assert abuse. 

You can also get the same functionality of switch() now with if blocks, which is a much better option than switch abuse. That's not why I'm arguing. My point is that assert's syntax is nice and simple.
An if block says 'I am meant to be here in production 
code' where as an assert says 'I am meant to be compiled out in 
production code'.

I don't like this "meant to be" mumbo-jumbo. Asserts are useful and elegant. So I use them and enjoy their elegance. If you don't like them, fine. Don't use them. Could the rest of us still keep them? Thank you.
Just say 'No' to assert abuse!

Friends don't let friends compile without asserts. ;) Asserts are the seat-belts of programming. You're not against seat-belts, are you? :p Cheers, --AJG.
Aug 16 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 16 Aug 2005 14:50:43 +0000 (UTC), AJG wrote:

 Hi,
 
AJG wrote:

 The idea that asserts (or worse, contracts in general) are only useful to the
 immediate programmer is misguided.

The idea that asserts are to be used for anything other than development is misguided. I don't know your background, but the idea of compiling out asserts in release builds has been in practice in C and C++ for quite a long while.

First off, D is not C, and D is not C++. D is supposed to be better than those two. C and C++, relatively speaking, are not safe languages. I hope that D would want to do better.

I think you missed the point. Other languages allow asserts to be removed, so therefore D is not doing something that is thought as bad by many other language designers.
 But, I'm going to play the devil's advocate:
 
 On the linux side, I use GCC. GCC compiles asserts in by default. In fact,
 according to the C standard, asserts _should be in_ by default, so GCC is
 rightly following this convention.
 
 In order to remove asserts, you specifically have to FORCE the symbol NDEBUG
 into your code. The verb "force" is not mine, it's in the very spec:
 
 http://www.opengroup.org/onlinepubs/009695399/functions/assert.html
 
 So, when I compile "release" code, I do something like:
 
 gcc -Wall -Pedantic -O3 <code>
 
 Whereas you would evidently do:
 
 gcc -DNDEBUG (...)
 
 See, that's _your_ decision. Just because you think so doesn't mean you should
 FORCE it upon the world. Specially when it reduces the safety of a function. I
 don't call that release code, I call that unsafe code.

This behaviour is identical to D, in that asserts are by default included and to exclude them you must do that explicitly. Code is only unsafe if there are no checks in it, and one can do checking without using assert().
 Let's go over that one again:
 Removing asserts unequivocally reduces the safety of a function. Period.

That is not universally true. I would have said 'removing checks reduces the detection of unsafe function behaviour'. The difference is that you seem to be saying that assert() is the only proper method to perform validation checks, but that is just not so.
 One last interesting bit is that even in -O3, the highest optimization level,
 asserts are _still_ left in the code (as they should) by the compiler.
 Therefore, asserts (and their safety) and optimization can be kept independent.

Just like D. The optimization switch does not effect asserts or contracts.
 On the windows side, I use VC++. VC++ does something wonderful in the form of
 VERIFY. It's a version of assert that never goes away. That's what I always use
 and I love it.
 
 Unfortunately, D doesn't have that. In fact, that would be a great compromise.
 If D were to introduce a permanent assert, e.g. verify(), then we could both
 have what we want.

Yep. A verify() statement that works like assert() but is not removed by "-release" *and* allows an additional coder specified message would be useful for many people. verify(a == b, "Special message to user");
 Assert is for validation of logic and *known* inputs 
(for example, validating that an arg is not null, or that an object was 
set to a specific state before the function was called), 

There is no such thing as a "known" input. Are you telling me you know, in advance, _every_, _single_ way your function is going to be called in the future? Every possibility? Every programmer? Every project and program?

Yes. a = sin(1.2) In this case, the input is known (1.2), but that's not what you were meaning was it ;-) I repeat: function argument validation must not use D assert() statement or in{} blocks because they can be removed without the coder knowing it. For example, the Release or QA manager recompiles it with "-release" (by accident?).
 That seems a bit unlikely to me (Perhaps you are an oracle?). Therefore, it is
 unsafe. You don't know how and when your function is going to be called.
Asserts
 are the guards that prevent bizarre calls from turning catastrophic. Leave them
 in! Or at least, let _me_ leave _mine_ in.

I repeat: assert() is not the only method to use for function argument validation.
and not for 
unknown inputs (what Derek referred to as data - user input, scripted 
data, anything that isn't known at compile time).

Oh, so then a "known input" is, by your definition, known at compile time. That's great. So I guess your asserts look something like this: const int Foo = 42; assert(1 == 1); assert("car" == "car"); assert(Foo == 42); Right?

Of course not. Now you're just being silly. My assert usage is more like this ... unittest{ assert( myfunc(1.2) == 42.0); assert( myfunc(0.0) == 0.0); assert( myfunc(real.init) == real.init); } That is, I use them to validate that the function logic is correct by supplying known input values for which I know the correct results. If the function returns incorrect results then I assume that the function (or sub functions) is using the wrong algorithm. Another usage is during specific debug sessions ... debug(REGRESSION) assert( data_in >= 0 ); where I'm testing prototype code for specific edge conditions or similar. Again, these are not expected to be released in a production edition because I would have handled these conditions by then. However they are useful for regression testing.
Well, those "known inputs" go into static asserts, not regular asserts.
 They would be _trivial_ as regular asserts.

Duh!
In C, whenever you 
need to validate unknown inputs you check it with an if block.

Maybe _you_ do that. That's verbose, more complex and less clear. OTOH, I use asserts for a lot of conditions that you might think will never happen, but, because of the nature of programs, you never know.

Its because asserts can be removed *and* that they provide poor feedback to end users, that it is currently better to use the more verbose techniques. I would rather real sqrt(real a) { validate( a >= 0, __FILE__, __LINE__, __TIMESTAMP__, sprintf("Cannot take the square root of (%s)." " It must be zero or higher", a)); than real sqrt(real a) { assert(a >= 0); any day. It provides much more useful feedback to developer and user alike.
 Just out of curiosity, what do you use asserts for, then? It must be for some
 truly trivial stuff, if I understand you correctly. Otherwise, if _not_
trivial,
 it is _wiped out_ in -release and all that non-trivial checking goes out the
 window. Do you see my point?

Yes, but I don't agree with you. My usage is not trivial as it validates function logic. The logic doesn't change once it gets to the production edition stage.
 So which one is it, trivial asserts or useful asserts?

Gee... let me think a bit ... Oh I know, I know, ... 42, right?
What you are trying to do is use assert in 
a manner that goes against its intended and standard use. It is not, in 
any language I know, meant for use in production code. Asserts are meant 
to be able to be compiled out, period.

Once again, that's your opinion. All I am asking is for the choice to be left to the programmer independent of the code being "production" or not. One solution is the -contracts argument. Another would be the verify() version that doesn't go away. Either one would be fine by me. Both would be even better.

I would support either or both these additions to D. -- Derek (skype: derek.j.parnell) Melbourne, Australia 17/08/2005 9:11:17 AM
Aug 16 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi,

 If D were to introduce a permanent assert, e.g. verify(), then we could both
 have what we want.

Yep. A verify() statement that works like assert() but is not removed by "-release" *and* allows an additional coder specified message would be useful for many people. verify(a == b, "Special message to user");

Agreed. There you go, proof that there _can_ be agreement in internet newsgroups. I like your suggestion. In fact, an even better way IMO would be: void verify(bool cond, ...); That way it can tunnel parameters to work like writefln() does right now. E.g.: verify(c == d, "c (%d) != d (%d)", c, d); What do you think?
 All I am asking is for the choice to be left to
 the programmer independent of the code being "production" or not. One solution
 is the -contracts argument. Another would be the verify() version that doesn't
 go away. Either one would be fine by me. Both would be even better.


Awesome. Walter, any chance of these things happening? 1) A version of assert, that is never eliminated, in the form of: void verify(bool cond, ...) /* throws VerificationError */; 2) A way to explicitly specify which contracts to include: DMD -contracts (...) // Include everything. DMD -contracts:in // Include pre-condition contracts. DMD -contracts:!out // Include everything except post-condition contracts. Or something similar (syntax is irrelevant to me). Thanks, --AJG.
Aug 17 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <de00mc$889$1 digitaldaemon.com>, AJG says...
Hi,

 If D were to introduce a permanent assert, e.g. verify(), then we could both
 have what we want.

Yep. A verify() statement that works like assert() but is not removed by "-release" *and* allows an additional coder specified message would be useful for many people. verify(a == b, "Special message to user");

Agreed. There you go, proof that there _can_ be agreement in internet newsgroups. I like your suggestion. In fact, an even better way IMO would be: void verify(bool cond, ...); That way it can tunnel parameters to work like writefln() does right now. E.g.: verify(c == d, "c (%d) != d (%d)", c, d); What do you think?
 All I am asking is for the choice to be left to
 the programmer independent of the code being "production" or not. One solution
 is the -contracts argument. Another would be the verify() version that doesn't
 go away. Either one would be fine by me. Both would be even better.


Awesome. Walter, any chance of these things happening?

This wouldn't be hard to do right now. Just write a function called "verify" and place it in object.d. Sean
Aug 17 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi,

Awesome. Walter, any chance of these things happening?

This wouldn't be hard to do right now. Just write a function called "verify" and place it in object.d.

But then how would I get line number and filename? Thanks, --AJG.
Aug 17 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <de07m7$dke$1 digitaldaemon.com>, AJG says...
Hi,

Awesome. Walter, any chance of these things happening?

This wouldn't be hard to do right now. Just write a function called "verify" and place it in object.d.

But then how would I get line number and filename?

Good point :p I think there are actually preprocessor macros you can use for this purpose (__FILE__ and __LINE__) but it's annoying having to pass them as arguments. Sean
Aug 18 2005
parent AJG <AJG_member pathlink.com> writes:
Hi,

This wouldn't be hard to do right now.  Just write a function called "verify"
and place it in object.d.

But then how would I get line number and filename?

Good point :p I think there are actually preprocessor macros you can use for this purpose (__FILE__ and __LINE__) but it's annoying having to pass them as arguments.

Yep, it'd be a little kludgy to have to pass those around ;). Plus the compiler wouldn't know that the function is "special," for cases like verify(false);. That kind of support needs to come from the compiler itself. I hope Walter considers adding this wonderful function. Benefits: 1) assert() doesn't have to change at all. Current code relying on assert would work identically. 2) Allows for writefln()-style variadic messages, which would come in very handy. 3) Provides line number / file name information. 4) The compiler can detect or eliminate dead code with it, and know when functions don't have to return. Thanks, --AJG. Cheers, --AJG.
Aug 18 2005
prev sibling parent reply "Unknown W. Brackets" <unknown simplemachines.org> writes:
 "Release" code should have nothing to do with contracts or safety.
 It should be about removing extra symbols, stripping useless sections,
 etc. Not safety. Not contracts. Well, IMHO, of course.

You're confusing -release with -O. The latter is used to optimize the code, and that's what you want (unless I'm mistaken.) In fact -release doesn't even do that at all. The -inline and -O options are completely separate. Neither is it "in D", it is in DMD. I haven't read anywhere in the spec that dictates these command line options must be common to all compilers - another one could easily make -release mean optimize, and -unsafe be no contracts, etc. -[Unknown]
Aug 18 2005
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 18 Aug 2005 20:17:22 -0700, Unknown W. Brackets wrote:


[snip]

 I haven't read anywhere in the spec 
 that dictates these command line options must be common to all compilers 
 - another one could easily make -release mean optimize, and -unsafe be 
 no contracts, etc.

A very good point. D is not DMD. -- Derek (skype: derek.j.parnell) Melbourne, Australia 19/08/2005 1:35:13 PM
Aug 18 2005
parent AJG <AJG_member pathlink.com> writes:
Hi,

 I haven't read anywhere in the spec 
 that dictates these command line options must be common to all compilers 
 - another one could easily make -release mean optimize, and -unsafe be 
 no contracts, etc.

A very good point. D is not DMD.

Even though the statement "D is not DMD" is mostly true, the original premise is wrong. If you are interested, see my other post for details. Cheers, --AJG.
Aug 19 2005
prev sibling parent reply AJG <AJG_member pathlink.com> writes:
In article <de3ivs$vku$1 digitaldaemon.com>, Unknown W. Brackets says...
 "Release" code should have nothing to do with contracts or safety.
 It should be about removing extra symbols, stripping useless sections,
 etc. Not safety. Not contracts. Well, IMHO, of course.

You're confusing -release with -O. The latter is used to optimize the code, and that's what you want (unless I'm mistaken.) In fact -release doesn't even do that at all. The -inline and -O options are completely separate.

I really don't think I am. What does "release" mean? To me, it means "do not include debugging information." What is this "information?" Well, symbols, sections, etc. that are only useful during debugging. Optimization ("-O", "-inline") is a whole other matter, which to me means, "make my code faster, more efficient, using whichever legal technique you can get away with." My point is that _neither_ "optimization," _nor_ "release," should have anything to do with safety, or at the very least, nothing to do with contracts. I think we've established that optimization already follows this "rule." So, IMO, optimization is fine. My problem is with "release", which _in addition_ to doing what it is supposed to do, it is also taking away the safety of my code in the form of removing contracts and checks. That's why I propose a "-contracts" argument which explicitly tells the compiler what you want it to do with your contracts and checks. So, "don't use -release" you say. That's not a good solution. I don't want to ship debug code. I don't want to ship debugging symbols. How should I, right now, specify that the compiler: 1) Leave ALL contracts/checks/safety IN. 2) Take ALL debugging information OUT. In other words, I do not think contracts are _solely_ "debugging" tools. They _help_ during debugging, but they are incredibly useful all around. They should be independent of debugging. One simple example: Array bounds checks. I'm not sure if those are called contracts or not. Doesn't matter. At any rate, these are currently _wiped out_ in -release. I think that's a really bad decision. Are you telling me you are so confident that you can guarantee that _all_ of your arrays, in _all_ of your code, will never, ever, overrun a single boundary once gone into production (i.e. once "released")? I can't say such a thing, which is why I would like a separate option to be able to leave my contracts and checks in. That's all I'm asking for, a choice to be able to properly do that.
Neither is it "in D", it is in DMD.  I haven't read anywhere in the spec 
that dictates these command line options must be common to all compilers 
- another one could easily make -release mean optimize, and -unsafe be 
no contracts, etc.

I beg to differ: Spec: http://www.digitalmars.com/d/dbc.html Example sentence: "For a release build of the code, the in and out code is not inserted." Nowhere in that page is DMD even mentioned, so I think it's speaking about the language in general. Otherwise, the spec is plain misleading. At any rate, the point is moot. I currently use DMD, and it looks to me like the only viable option to use the latest version of D. Once we start seeing multitudes of compilers (like C++), the perhaps the point would be more relevant. Moreover, I just took a look at GDC, the one other "compiler," and I found this mapping table: http://home.earthlink.net/~dvdfrdmn/d/ -debug => -fdebug -release => -frelease So it looks like fully 100% of the D language, specification & implementation, does what I'm talking about, which is taking contracts out for production code. This doesn't bode well for safety. Cheers, --AJG.
Aug 19 2005
next sibling parent Mike Parker <aldacron71 yahoo.com> writes:
AJG wrote:
 In article <de3ivs$vku$1 digitaldaemon.com>, Unknown W. Brackets says...

 
 I really don't think I am. What does "release" mean? To me, it means "do not
 include debugging information." What is this "information?" Well, symbols,
 sections, etc. that are only useful during debugging.

What "release" means to you is irrelevant. What it means to DMD is what's important here (from http://www.digitalmars.com/d/dcompiler.htm): -release compile release version, which means not generating code for contracts and asserts Notice it says nothing about debugging symbols, which are only included when you use pass -g: -g add symbolic debug info In your original post, you said: ******************************************************************** /First, I was happily coding in D under -debug. Then, I started using std.boxer which requires that I use -release because of unresolved linking. So I add -release (in _addition_ to -debug) and all hell breaks lose. 1) asserts no longer display anything meaningful; they segfault. 2) pre-condition (in) contracts disappear altogether./ ******************************************************************** Notice what the docs say about -debug: -debug compile in debug code Debug code in this case is anything following a 'debug' statement in your code, and has nothig to do with contracts or asserts. The compiler already does *exactly* what you want it to. The whole point of this thread is moot. The problem stems from your understanding of the terms 'release' and 'debug', which in the case of the D compiler do not mean what they have traditionally meant in other language tools. Contracts and asserts are enabled by default. If you don't beleive me: ******************************************************************** void myfunc() in { assert(false); } body { printf("Boo!\n"); } void main() { myfunc(); } ******************************************************************** Compile with no command line args (dmd foo.d), then run it to see what happens. So -release doesn not mean 'compile with optimizations and whatever else release mode traditionally does', but rather 'turn off contracts and asserts'.
 So, "don't use -release" you say. That's not a good solution. I don't 
 want to
 ship debug code. I don't want to ship debugging symbols. How should 

 now, specify that the compiler:

Simply by omitting -g (thereby leaving out debugging symbols) and also omitting -debug (thereby leaving out everything in "debug" statements"). And if you also omit release, you get to keep your contracts and asserts.
Aug 19 2005
prev sibling parent reply "Unknown W. Brackets" <unknown simplemachines.org> writes:
 Are you telling me you are so confident that you can guarantee that _all_ of
 your arrays, in _all_ of your code, will never, ever, overrun a single boundary
 once gone into production (i.e. once "released")?

No, I also prefer to ship with such things on (well, with the option of the faster version without the checks) but that's my choice. By your definitions of release, that's what DMD generates (as mentioned) with no arguments at all. Personally, I've never liked the "debug/release" mentality, anyway. I think of it as many more stages (debugging, testing, etc.)
 "For a release build of the code, the in and out code is not inserted."

The wording can be changed, but there's nothing in that sentence that forces anyone not to have a contracts option. It suggests that, as many programmers prefer, such things as contracts and array bounds checking won't be included in release. I know many programmers who would look at you as if you had just sworn something strong if you suggested shipping code with array bounds checking in it. Yes, you don't agree - and yes, I prefer my users to be able to easily report bugs to me, but this is entirely preference. Long debates on this have been posted in this very newsgroup. -[Unknown]
Aug 19 2005
parent reply AJG <AJG_member pathlink.com> writes:
Hi,

 Are you telling me you are so confident that you can guarantee that _all_ of
 your arrays, in _all_ of your code, will never, ever, overrun a single boundary
 once gone into production (i.e. once "released")?

the faster version without the checks) but that's my choice. By your definitions of release, that's what DMD generates (as mentioned) with no arguments at all.

This appears to be true (doing some checks right now), so in this respect, you are right. I was wrong to think there was no way of accomplishing that task. My worry is that "-release" is a misnomer. _If_ indeed _all_ it does is remove contracts, then it should be called something else. "-nocontracts", "-unsafe", or whatever. Using "-release" implies production code == contractless code.
Personally, I've never liked the "debug/release" mentality, anyway.  I 
think of it as many more stages (debugging, testing, etc.)

Very much agreed.
 "For a release build of the code, the in and out code is not inserted."

The wording can be changed, but there's nothing in that sentence that forces anyone not to have a contracts option.

Well, it'd certainly like to see that option. I would very much prefer to have a "-contracts" option where I can explicitly tell the compiler to leave them in, instead of relying on iffy defaults. Call it a safety measure.
I know many programmers who would look at you as if you had just sworn 
something strong if you suggested shipping code with array bounds 
checking in it.

Unless those programmers are working on extremely speed-sensitive code, my opinion is that they are just plain wrong. Removing array bounds for _regular_ code is a combination of premature optimization and thoughtlessness. If indeed the code is _so_ speed-sensitive, it should probably be in assembly. Profile the code, see where the bottleneck is, and work with that part (or hand code it in asm). It is understandable to lose safety, readability, portability, etc... where it truly matters.
Yes, you don't agree - and yes, I prefer my users to be 
able to easily report bugs to me, but this is entirely preference.  Long 
debates on this have been posted in this very newsgroup.

Hehe, I guess the wrong side has been winning? ;) Cheers, --AJG.
Aug 19 2005
next sibling parent "Unknown W. Brackets" <unknown simplemachines.org> writes:
Walter always wins (except when he gives in), and so he is always the 
right side :P.  Thus the right side has been winning.

Seriously, though, most of the work I do is on web servers.  For me, the 
idea that speed is unimportant for anything but "speed sensitive" code 
is rediculous.  Many of my clients would definitely prefer the faster 
version, even with any possibility of segfaults.

-[Unknown]
Aug 19 2005
prev sibling parent Mike Parker <aldacron71 yahoo.com> writes:
AJG wrote:

 Well, it'd certainly like to see that option. I would very much prefer to have
a
 "-contracts" option where I can explicitly tell the compiler to leave them in,
 instead of relying on iffy defaults. Call it a safety measure.

You don't need to tell the compiler to leave them in. They are in by default. Nothing iffy about it. 'dmd mysource.d' gives you contracts and asserts.
Aug 20 2005