June 20, 2013
A)
does assert(foo) where foo is an expression that cat be evaluated at
compile time (eg via CTFE etc) behave same as assert(true)/assert(false)?


B)

It is usually "bad practice" to keep an assert in release
> ("assert(false)"), because the code should already have been checked, and
> you shouldn't pay for the check in release.
> BUT: Since the code is theoretically unreachable, there is no real world
> penalty to the check anyway, so you might put it in anyways, on the off
> chance it saves your but (IMO).


What do you mean by 'you shouldn't pay for the check in release' ?
If the boolean argument is known at compile time, there is no check, so no
overhead right? (ie compiler should optimize away)





On Thu, Jun 20, 2013 at 2:25 PM, Jonathan M Davis <jmdavisProg@gmx.com>wrote:

> On Thursday, June 20, 2013 22:21:28 Joseph Rushton Wakeling wrote:
> > In my case it was a bunch of if/else where the program should return from one of the blocks. I saw comparable cases in RandomCover with an assert(false) at the very end of the function, so thought I'd better
> tweak
> > my code accordingly.
>
> Putting it at the end of the function is unnecessary. The compiler already does that for you.
>
> - Jonathan M Davis
>


June 20, 2013
On Thursday, June 20, 2013 15:45:14 Timothee Cour wrote:
> A)
> does assert(foo) where foo is an expression that cat be evaluated at
> compile time (eg via CTFE etc) behave same as assert(true)/assert(false)?

If it _is_ known at compile time, then yes, but simply calling a function that _could_ be called during compile time won't result in it being checked at compile time.

> 
> B)
> 
> It is usually "bad practice" to keep an assert in release
> 
> > ("assert(false)"), because the code should already have been checked, and
> > you shouldn't pay for the check in release.
> > BUT: Since the code is theoretically unreachable, there is no real world
> > penalty to the check anyway, so you might put it in anyways, on the off
> > chance it saves your but (IMO).
> 
> What do you mean by 'you shouldn't pay for the check in release' ?
> If the boolean argument is known at compile time, there is no check, so no
> overhead right? (ie compiler should optimize away)

It's only optimized away if the section of code that it's in is optimized away, and unreachable code is not necessarily optimized away. The compiler would have to determine that it's unreachable in order to do that, and it frequently can't do that. And assert(false) is turned into a HLT instruction with -release, so it never goes away because of -release, unlike other assertions.

- Jonathan M Davis
June 20, 2013
On 06/20/2013 11:36 PM, Jonathan M Davis wrote:
>> ... one is necessary as it's in a function that is supposed to return a value.
> 
> I don't think that that's supposed to be necessary. The only reason that that should happen is if the compiler can deterimine that the execution can definitely reach the end of the function.

It's in diceImpl:

    private size_t diceImpl(Rng, Range)(ref Rng rng, Range proportions)
    if (isForwardRange!Range && isNumeric!(ElementType!Range) && isForwardRange!Rng)
    {
        double sum = reduce!("(assert(b >= 0), a + b)")(0.0, proportions.save);
        enforce(sum > 0, "Proportions in a dice cannot sum to zero");
        immutable point = uniform(0.0, sum, rng);
        assert(point < sum);
        auto mass = 0.0;

        size_t i = 0;
        foreach (e; proportions)
        {
            mass += e;
            if (point < mass) return i;
            i++;
        }
        // this point should not be reached
        assert(false);
    }

Obviously one can see logically that this assert will never be reached, but I don't think there's anything the compiler can pick up on to be certain.

Incidentally, I just realized that with diceImpl, Phobos has a very nice function in place to support a simple (though possibly inefficient) implementation of the Barabasi-Albert algorithm for generating scale free networks ... :-)
June 21, 2013
On Thursday, 20 June 2013 at 23:36:35 UTC, Joseph Rushton Wakeling wrote:
> On 06/20/2013 11:36 PM, Jonathan M Davis wrote:
>>> ... one is necessary as it's in a function that is supposed to return a
>>> value.
>> 
>> I don't think that that's supposed to be necessary. The only reason that that should happen is if the compiler can deterimine that the execution can definitely reach the end of the function.
>
> It's in diceImpl:
>
>     private size_t diceImpl(Rng, Range)(ref Rng rng, Range proportions)
>     if (isForwardRange!Range && isNumeric!(ElementType!Range) && isForwardRange!Rng)
>     {
>         double sum = reduce!("(assert(b >= 0), a + b)")(0.0, proportions.save);
>         enforce(sum > 0, "Proportions in a dice cannot sum to zero");
>         immutable point = uniform(0.0, sum, rng);
>         assert(point < sum);
>         auto mass = 0.0;
>
>         size_t i = 0;
>         foreach (e; proportions)
>         {
>             mass += e;
>             if (point < mass) return i;
>             i++;
>         }
>         // this point should not be reached
>         assert(false);
>     }
>
> Obviously one can see logically that this assert will never be reached, but I
> don't think there's anything the compiler can pick up on to be certain.

Reading that code, it's not immediately obvious to me: The assert makes it self documenting.

In any case, this goes back to what I first said: If you remove that assert, the compiler will complain that not all paths return.
June 21, 2013
On 06/21/2013 09:51 AM, monarch_dodra wrote:
> Reading that code, it's not immediately obvious to me: The assert makes it self documenting.

I did also have to think about it for a few seconds.  You have a sum of values from an array; you generate a uniformly-distributed random number point in [0.0, sum); you sequentially sum values from the same array, and return when that partial sum ("mass") exceeds the value of point.  Since point < sum you must do this eventually, but the compiler has no way to recognize that the maximum possible value of the variable mass will inevitably exceed the value of point.

> In any case, this goes back to what I first said: If you remove that assert, the compiler will complain that not all paths return.

Indeed. :-)
June 21, 2013
On Thu, 20 Jun 2013 15:48:38 -0400, Joseph Rushton Wakeling <joseph.wakeling@webdrake.net> wrote:

> Is it considered good/recommended practice to insert an assert(false) statement
> in parts of the code that should be unreachable?  Or simply an optional choice
> that may be useful for debugging?

I think it's more than good practice, the compiler may require it if it cannot prove via flow analysis that you are not forgetting to return a value.

Note that assert(false) can make the compiler generate code differently, if the compiler can prove the function never returns.  I'm more fuzzy on this detail.

-Steve
June 21, 2013
On 06/21/2013 02:56 AM, Joseph Rushton Wakeling wrote:

> I did also have to think about it for a few seconds.  You have
> a sum of values from an array; you generate a
> uniformly-distributed random number point in [0.0, sum); you
> sequentially sum values from the same array, and return when
> that partial sum ("mass") exceeds the value of point.  Since
> point < sum you must do this eventually

I spent a considerable amount of time reading that function as well. :)

I was afraid whether two separate floating point sums would give the same result. After all, the initial sum is a 'double' but the type of the elements of 'proportions' may be different. (I don't know the answer.)

Ali

1 2
Next ›   Last »