Thread overview
Conditional compilation for non-release version
Apr 28, 2012
bearophile
Apr 28, 2012
Timon Gehr
Apr 28, 2012
F i L
April 28, 2012
Hello all,

I've just been reading through this page: http://dlang.org/version.html

Is there a way to put in place a conditional segment of code that is included if the code is _not_ compiled with the -release flag?

Of course I can put in a debug statement, but that would require me to compile with -debug.  I'd like the opposite, that unless I explicitly specify the code as release-ready, the specified set of checks will be performed.

The reason I'm asking is because the checks I want to perform are of the form,

    foreach(x; myVeryLargeArray) {
        assert(/* ... some condition about x */);
    }

... and I'm concerned that with the foreach() loop in place, it will slow down the code even if the assert() statements are ignored at compile time.  So I'd like to be able to do something instead like,

    version(!release)
    {
        foreach(x; myVeryLargeArray) {
            assert(/* ... some condition about x */);
        }
    }

... is this possible?

Thanks & best wishes,

    -- Joe
April 28, 2012
Joseph Rushton Wakeling:

> Is there a way to put in place a conditional segment of code that is included if the code is _not_ compiled with the -release flag?

Contract programming? D is designed to make it hard on purpose to
do what you want to do.


> The reason I'm asking is because the checks I want to perform are of the form,
>
>     foreach(x; myVeryLargeArray) {
>         assert(/* ... some condition about x */);
>     }
>
> ... and I'm concerned that with the foreach() loop in place, it will slow down the code even if the assert() statements are ignored at compile time.  So I'd like to be able to do something instead like,
>
>     version(!release)
>     {
>         foreach(x; myVeryLargeArray) {
>             assert(/* ... some condition about x */);
>         }
>     }
>
> ... is this possible?

My suggestion is to use a pure helper predicate, possibly nothrow
too (a pure lambda too is OK):

bool isGood(MyType x) pure {
...
}

foreach(x; myVeryLargeArray) {
     assert(isGood(x));
}


The purity of the predicate is almost necessary, to be sure your
program behavior doesn't change between release and non-release
mode.

Bye,
bearophile
April 28, 2012
On 04/28/2012 02:05 PM, Joseph Rushton Wakeling wrote:
> Hello all,
>
> I've just been reading through this page: http://dlang.org/version.html
>
> Is there a way to put in place a conditional segment of code that is
> included if the code is _not_ compiled with the -release flag?
>
> Of course I can put in a debug statement, but that would require me to
> compile with -debug. I'd like the opposite, that unless I explicitly
> specify the code as release-ready, the specified set of checks will be
> performed.
>
> The reason I'm asking is because the checks I want to perform are of the
> form,
>
> foreach(x; myVeryLargeArray) {
> assert(/* ... some condition about x */);
> }
>
> ... and I'm concerned that with the foreach() loop in place, it will
> slow down the code even if the assert() statements are ignored at
> compile time. So I'd like to be able to do something instead like,
>
> version(!release)
> {
> foreach(x; myVeryLargeArray) {
> assert(/* ... some condition about x */);
> }
> }
>
> ... is this possible?
>
> Thanks & best wishes,
>
> -- Joe


assert({
  /* code you want to execute in non-release mode */
  return true;
}());
April 28, 2012
asserts aren't compiled into release builds (except assert(false)). So, if the loop only contains asserts, the compiler *should* be able to strip out the loop altogether. I don't know if DMD actually does that, though.

Or you could use debug statements:

    debug foreach (x; largeArray) {

        ...
    }

you'll need to compile with "-debug" for the loop to be included.
April 28, 2012
On 28/04/12 15:03, F i L wrote:
> Or you could use debug statements:

Yes, that was what I wanted to avoid -- I wanted the tests to be there by default, not only when debugging ... :-)

AFAICS the foreach loop probably does get optimized out by the compiler (I'm using GDC); if anything is left, the time it adds is negligible compared to the natural variation in runtime of the program.

In the end I decided to play ultra-safe and add assert() statements in every context where the array entries are used.  Those extra checks don't actually add anything to the non-release runtime, so far as I can tell.