www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why assert is in the language?

reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Yes, why? It could be implemented in object.d in a similar fashion as  
std.contracts.enforce. Does it do anything special that a library function  
couldn't?

Tomek
Jun 22 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 22 Jun 2010 17:07:02 -0400, Tomek Sowiński <just ask.me> wrote:

 Yes, why? It could be implemented in object.d in a similar fashion as  
 std.contracts.enforce. Does it do anything special that a library  
 function couldn't?
all calls to assert are removed by the compiler in release mode. I don't think there's a way to implement that via a library (it would be nice though!) -Steve
Jun 22 2010
next sibling parent reply Michal Minich <michal.minich gmail.com> writes:
On Tue, 22 Jun 2010 17:30:23 -0400, Steven Schveighoffer wrote:

 On Tue, 22 Jun 2010 17:07:02 -0400, Tomek Sowiński <just ask.me> wrote:
 
 Yes, why? It could be implemented in object.d in a similar fashion as
 std.contracts.enforce. Does it do anything special that a library
 function couldn't?
all calls to assert are removed by the compiler in release mode. I don't think there's a way to implement that via a library (it would be nice though!) -Steve
modifying 'debug' attribute which decorate a function, which new meaning that all calls to it are removed in release mode, might do the trick :) it also could be useful for logging. AFAIK, now the attribute means that the function does not exists in debug mode, but that also means that you must mark all calls to it with 'debug' which I don't find so much useful...
Jun 22 2010
parent reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 22-06-2010 o 23:55:29 Michal Minich <michal.minich gmail.com>  =

napisa=B3(a):

 On Tue, 22 Jun 2010 17:30:23 -0400, Steven Schveighoffer wrote:

 On Tue, 22 Jun 2010 17:07:02 -0400, Tomek Sowi=F1ski <just ask.me> wr=
ote:
 Yes, why? It could be implemented in object.d in a similar fashion a=
s
 std.contracts.enforce. Does it do anything special that a library
 function couldn't?
all calls to assert are removed by the compiler in release mode. I don't think there's a way to implement that via a library (it would b=
e
 nice though!)

 -Steve
modifying 'debug' attribute which decorate a function, which new meani=
ng
 that all calls to it are removed in release mode, might do the trick :=
)
 it also could be useful for logging.

 AFAIK, now the attribute means that the function does not exists in de=
bug
 mode, but that also means that you must mark all calls to it with 'deb=
ug'
 which I don't find so much useful...
There's a better way: void assert_(string file =3D __FILE__, uint line =3D __LINE__)(bool pred= , lazy = string msg =3D null) { version(unittest) if (!pred) throw new AssertError(msg, file, line); } If unittesting is off, it is inlined and all calls vanish. Someone mentioned the assert(0) special case. That could be implemented = = like: void fail() { asm { // HLT instruction... } } Following benefits spring to mind: - It's clear that fail is something different than assert. Unlike asse= rt = vs. assert(0). - The compiler can be made aware of fail() to recognize and refuse to = = compile dead code. - Documentation can be added with no additional effort; newbies can re= ad = it straight from a tooltip provided by the IDE. - Curious users are free to introspect the implementation. So I ask again -- what benefits on top of that list can having assert in= = the language give? Tomek
Jun 23 2010
next sibling parent reply Jonathan M Davis <jmdavisProg gmail.com> writes:
Tomek Sowiński wrote:

 There's a better way:
 
 void assert_(string file = __FILE__, uint line = __LINE__)(bool pred, lazy
 string msg = null) {
      version(unittest)
          if (!pred)
              throw new AssertError(msg, file, line);
 }
 
 If unittesting is off, it is inlined and all calls vanish.
 
 Someone mentioned the assert(0) special case. That could be implemented
 like:
 
 void fail() {
      asm {
           // HLT instruction...
      }
 }
 
 Following benefits spring to mind:
   - It's clear that fail is something different than assert. Unlike assert
 vs. assert(0).
   - The compiler can be made aware of fail() to recognize and refuse to
 compile dead code.
   - Documentation can be added with no additional effort; newbies can read
 it straight from a tooltip provided by the IDE.
   - Curious users are free to introspect the implementation.
 
 So I ask again -- what benefits on top of that list can having assert in
 the language give?
 
 
 Tomek
1. The compiler itself uses assert. Given that it uses assert, even if assert isn't a keyword, you won't be able to use it for anything else. Either it's going to be a keyword or it's going to be like Object and be something defined that's always defined, so you can't use the name for anything else. At that point, it might as well be a keyword - on top of which making it a keyword makes it so that IDEs are likely to highlight it accordingly, and it will be more obvious in the code. 2. It's almost certainly more efficient as a keyword. As a keyword, there likely aren't any function calls going on beyond what's being asserted. If it were an actual function, given that it's used primarily in debug mode, it almost certainly wouldn't be inlined, and it would slow down the code that much more. 3. Making assert a keyword makes it easier for the compiler to treat it specially. It knows about assert and what to do with it without having to examine every function to see whether it's assert and therefore have to treat it differently. The closest to anything, that I'm aware of, which is treated specially in that manner is Object, and unlike examining each function to see whether it should treat it specially, it will be quite straightforward with Object because it only has to deal with it specially when dealing with class declarations, and since it _always_ inserts the Object stuff in that case, it's a no-brainer. Having to look at each function to see whether it's on the list of functions to treat specially would have to slow compilation down. Not to mention, Walter's trying to keep D such that it's fairly easy to compile so that tools (including the compiler) will have a much easier time handling it and are less likely to be buggy. If it starts having to treat functions in a special way, then that's just going to have to complicate things. 4. Given that Walter is definitely pushing design by contracts and unit tests - both of which need assertions - it makes perfect sense to include assertions in the language itself. 5. I see _0_ downsides to assert being in the language itself. Sure, there may be ways to make assert better, but that doesn't require it to be done in library code. We might as well put it in the language itself and give the compiler the chance to deal with it specially. - Jonathan M Davis
Jun 23 2010
parent =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 24-06-2010 o 01:39:35 Jonathan M Davis <jmdavisProg gmail.com>  =

napisa=B3(a):

 Tomek Sowi=F1ski wrote:

 There's a better way:

 void assert_(string file =3D __FILE__, uint line =3D __LINE__)(bool p=
red, =
 lazy
 string msg =3D null) {
      version(unittest)
          if (!pred)
              throw new AssertError(msg, file, line);
 }

 If unittesting is off, it is inlined and all calls vanish.

 Someone mentioned the assert(0) special case. That could be implement=
ed
 like:

 void fail() {
      asm {
           // HLT instruction...
      }
 }

 Following benefits spring to mind:
   - It's clear that fail is something different than assert. Unlike  =
 assert
 vs. assert(0).
   - The compiler can be made aware of fail() to recognize and refuse =
to
 compile dead code.
   - Documentation can be added with no additional effort; newbies can=
=
 read
 it straight from a tooltip provided by the IDE.
   - Curious users are free to introspect the implementation.

 So I ask again -- what benefits on top of that list can having assert=
in
 the language give?


 Tomek
1. The compiler itself uses assert. Given that it uses assert, even if=
 assert isn't a keyword, you won't be able to use it for anything else.=
 Either it's going to be a keyword or it's going to be like Object and =
be
 something defined that's always defined, so you can't use the name for=
 anything else. At that point, it might as well be a keyword - on top o=
f
 which making it a keyword makes it so that IDEs are likely to highligh=
t =
 it
 accordingly, and it will be more obvious in the code.

 2. It's almost certainly more efficient as a keyword. As a keyword, th=
ere
 likely aren't any function calls going on beyond what's being asserted=
. =
 If
 it were an actual function, given that it's used primarily in debug  =
 mode, it
 almost certainly wouldn't be inlined, and it would slow down the code =
=
 that
 much more.

 3. Making assert a keyword makes it easier for the compiler to treat i=
t
 specially. It knows about assert and what to do with it without having=
to
 examine every function to see whether it's assert and therefore have t=
o
 treat it differently. The closest to anything, that I'm aware of, whic=
h =
 is
 treated specially in that manner is Object, and unlike examining each
 function to see whether it should treat it specially, it will be quite=
 straightforward with Object because it only has to deal with it specia=
lly
 when dealing with class declarations, and since it _always_ inserts th=
e
 Object stuff in that case, it's a no-brainer. Having to look at each
 function to see whether it's on the list of functions to treat special=
ly
 would have to slow compilation down. Not to mention, Walter's trying t=
o =
 keep
 D such that it's fairly easy to compile so that tools (including the
 compiler) will have a much easier time handling it and are less likely=
=
 to be
 buggy. If it starts having to treat functions in a special way, then  =
 that's
 just going to have to complicate things.

 4. Given that Walter is definitely pushing design by contracts and uni=
t
 tests - both of which need assertions - it makes perfect sense to incl=
ude
 assertions in the language itself.

 5. I see _0_ downsides to assert being in the language itself. Sure,  =
 there
 may be ways to make assert better, but that doesn't require it to be  =
 done in
 library code. We might as well put it in the language itself and give =
the
 compiler the chance to deal with it specially.

 - Jonathan M Davis
OK, I get it. Thanks for your elaborate answer. Tomek
Jun 24 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 23 Jun 2010 16:06:48 -0400, Tomek Sowiński <just ask.me> wrote:

 Dnia 22-06-2010 o 23:55:29 Michal Minich <michal.minich gmail.com>  
 napisał(a):

 On Tue, 22 Jun 2010 17:30:23 -0400, Steven Schveighoffer wrote:

 On Tue, 22 Jun 2010 17:07:02 -0400, Tomek Sowiński <just ask.me> wrote:

 Yes, why? It could be implemented in object.d in a similar fashion as
 std.contracts.enforce. Does it do anything special that a library
 function couldn't?
all calls to assert are removed by the compiler in release mode. I don't think there's a way to implement that via a library (it would be nice though!) -Steve
modifying 'debug' attribute which decorate a function, which new meaning that all calls to it are removed in release mode, might do the trick :) it also could be useful for logging.
That means you have to compile with -debug switch. Assert is enabled without any switches.
 AFAIK, now the attribute means that the function does not exists in  
 debug
 mode, but that also means that you must mark all calls to it with  
 'debug'
 which I don't find so much useful...
There's a better way: void assert_(string file = __FILE__, uint line = __LINE__)(bool pred, lazy string msg = null) { version(unittest) if (!pred) throw new AssertError(msg, file, line); } If unittesting is off, it is inlined and all calls vanish.
Only if you specify -inline on the command line... Not a good option.
 Someone mentioned the assert(0) special case. That could be implemented  
 like:

 void fail() {
      asm {
           // HLT instruction...
      }
 }

 Following benefits spring to mind:
   - It's clear that fail is something different than assert. Unlike  
 assert vs. assert(0).
   - The compiler can be made aware of fail() to recognize and refuse to  
 compile dead code.
   - Documentation can be added with no additional effort; newbies can  
 read it straight from a tooltip provided by the IDE.
   - Curious users are free to introspect the implementation.

 So I ask again -- what benefits on top of that list can having assert in  
 the language give?
Well, first, you can't implement it in the library as currently designed without requiring special switches for normal compilation. No need to have any more reasons. What are the drawbacks? "keyword bloat" is an academic measure, and doesn't count ;) -Steve
Jun 24 2010
prev sibling parent reply Jonathan M Davis <jmdavisProg gmail.com> writes:
Steven Schveighoffer wrote:

 On Tue, 22 Jun 2010 17:07:02 -0400, Tomek Sowiński <just ask.me> wrote:
 
 Yes, why? It could be implemented in object.d in a similar fashion as
 std.contracts.enforce. Does it do anything special that a library
 function couldn't?
all calls to assert are removed by the compiler in release mode. I don't think there's a way to implement that via a library (it would be nice though!) -Steve
Also IIRC, the compiler uses assert(0) to ensure that functions blow up at runtime if you manage to hit the end of them without a return statement. And it's not like it hurts anything to make it part of the language. Also, having them as part of the language gives the compiler better control of them and allows it to know more about them in order to treat them in a special manner, which it could not do with library functions. All in all, there isn't really a downside (as far as I'm aware of anyway) to having them in the language itelf, and it helps the compiler deal with them. - Jonathan M Davis
Jun 22 2010
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Jonathan M Davis wrote:
 Steven Schveighoffer wrote:
 all calls to assert are removed by the compiler in release mode.  I 
don't
 think there's a way to implement that via a library (it would be nice
 though!)
 Also IIRC, the compiler uses assert(0) to ensure that functions blow 
up at
 runtime if you manage to hit the end of them without a return statement.
I just read in TDPL that the assert(0) calls in user code are not removed even in release mode. Ali
Jun 22 2010
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 06/22/2010 05:36 PM, Ali Çehreli wrote:
 Jonathan M Davis wrote:
  > Steven Schveighoffer wrote:

  >> all calls to assert are removed by the compiler in release mode. I
 don't
  >> think there's a way to implement that via a library (it would be nice
  >> though!)

  > Also IIRC, the compiler uses assert(0) to ensure that functions blow
 up at
  > runtime if you manage to hit the end of them without a return statement.

 I just read in TDPL that the assert(0) calls in user code are not
 removed even in release mode.

 Ali
Really? // test.d void main(){ assert(0); } $ dmd test -release $ ./test Segmentation fault (core dumped) good job, dmd. Can anyone see if anything is going on here?
Jun 22 2010
parent Lutger <lutger.blijdestijn gmail.com> writes:
Ellery Newcomer wrote:

 On 06/22/2010 05:36 PM, Ali Çehreli wrote:
 Jonathan M Davis wrote:
  > Steven Schveighoffer wrote:

  >> all calls to assert are removed by the compiler in release mode. I
 don't
  >> think there's a way to implement that via a library (it would be nice
  >> though!)

  > Also IIRC, the compiler uses assert(0) to ensure that functions blow
 up at
  > runtime if you manage to hit the end of them without a return statement.

 I just read in TDPL that the assert(0) calls in user code are not
 removed even in release mode.

 Ali
Really? // test.d void main(){ assert(0); } $ dmd test -release $ ./test Segmentation fault (core dumped) good job, dmd. Can anyone see if anything is going on here?
According to TDPL, assert(false) is treated specially and never removed. It serves two purposes: - portable way of issuing the HLT instruction - telling the compiles that everything after is dead code, the compiler recognizes the meaning assert(false)
Jun 23 2010
prev sibling parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 22.06.2010 23:07, schrieb Tomek Sowiñski:
 Yes, why? It could be implemented in object.d in a similar fashion as
 std.contracts.enforce. Does it do anything special that a library function
 couldn't?

 Tomek
what about static assert?
Jun 22 2010
parent =?utf-8?B?VG9tZWsgU293acWEc2tp?= <just ask.me> writes:
Dnia 23-06-2010 o 07:05:42 dennis luehring <dl.soluz gmx.net> napisa=C5=82=
(a):

 Am 22.06.2010 23:07, schrieb Tomek Sowi=C3=B1ski:
 Yes, why? It could be implemented in object.d in a similar fashion as=
 std.contracts.enforce. Does it do anything special that a library  =
 function
 couldn't?

 Tomek
what about static assert?
I was asking about runtime assertions. But actually, that might be the first decent reason to keep assert as a = = keyword. Although there's no problem implementing it as in C++ (using = specialization of templates), the syntax nicely correlates with static i= f. Tomek
Jun 23 2010