September 14, 2005
Sean Kelly wrote:
> In article <dg80p3$2m8s$1@digitaldaemon.com>, James Dunne says...
> 
>>The hardware does trap such cases.  It's called a signalling (or noisy) NaN.  Most NaNs, however, are quiet NaNs.  D's float.nan is a quiet NaN, which does not signal when evaluated.  I'm not an expert on the IEEE floating point spec by any means.
>>
>>I'm also not quite sure how the signal from the FPU gets to the CPU to the application... I believe on Linux it is achieved with a SIGFPE signal sent to the app, which must trap it and handle it accordingly. I'm not sure how easy or difficult it would be to achieve the same effect using exceptions.
> 
> 
> SIGFPE is a standard C signal so it should work on Windows as well.  Now that I
> think about it, std.c.fenv has functions to specify floating-point behavior,
> though I've never actually used them.  There's a copy of a D header here:
> 
> http://svn.dsource.org/projects/ares/trunk/src/ares/std/c/fenv.d
> 
> 
> Sean

Even quiet NANs will trigger an exception when they are used in <,==,< comparisons, and they also trigger exceptions if they arise during a calculation. If D were to provide an option to make uninitialized variables be SNANs, you'd have immediate, 100% detection, but even with QNANs you'll catch them easily.
Would work just as well in release mode as in debug mode.
Heck, in debug mode you could use the bits inside the SNAN to be an index into a table of all variables in the program, so the error message could be:
floating point variable classY.func2().somevar was used before being initialised.
September 14, 2005
In article <1otsutm9b7edw$.p5znknydurvg.dlg@40tude.net>, Derek Parnell says...
>
>On Tue, 13 Sep 2005 20:08:02 -0400, Jarrett Billingsley wrote:
>
>> "Derek Parnell" <derek@psych.ward> wrote in message news:12zsfnc0t7lua.1wbg7upo8ws6s$.dlg@40tude.net...
>>> I haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc....
>> 
>> This:
>> 
>> (a < b) ? (a) : (b) = 15;
>> 
>> Would be the same as:
>> 
>> if(a < b)
>>     a = 15;
>> else
>>     b = 15;
>> 
>> So it's using the ?: to select the destination of the assignment instead of the source.
>
>Okay, so the general form would be ...
>
>  (BooleanExpression) ? (Identifier1) : (Identifier2) = Expression;
>
>which would be equivalent to  ...
>
>   { // Start a scoping block.
>     Typeof(Expression) Temp = Expression;
>     if (BooleanExpression == true)
>       Identifier1 = Temp;
>     else
>       Identifier2 = Temp;
>   }

Yes.

Now consider to write 5 successive scopes and compare it with the ?: notation.

Thomas


September 14, 2005
Thomas Kühne wrote:
> idea:
> "() ? (A) : (B) = rvalue;" is legal, if A and B are legal lvalues.
> 
> sample code:
> 	int a = 3;
> 	int b = 7;
> 	
> 	((a > b) ? (a) : (b)) = a*b + (b << 1) - (a >> 1) * (a & b);
> 
> reason:
> Limit code duplication and use of temporary variables in order to reduce
> the bug-proneness of complex evaluations.

You can do

    *((a > b) ? (&a) : (&b)) = a*b + (b << 1) - (a >> 1) * (a & b);

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:- C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on the 'group where everyone may benefit.
September 14, 2005
Derek Parnell wrote:

[...]
> Okay, so the general form would be ...
[...]
>      Typeof(Expression) Temp = Expression;
[...]

No. Because, D has at least that discontinuity with overloaded functions.

-manfred
September 14, 2005
On Wed, 14 Sep 2005 14:29:57 +0000 (UTC), Thomas Kühne wrote:

> In article <1otsutm9b7edw$.p5znknydurvg.dlg@40tude.net>, Derek Parnell says...
>>
>>On Tue, 13 Sep 2005 20:08:02 -0400, Jarrett Billingsley wrote:
>>
>>> "Derek Parnell" <derek@psych.ward> wrote in message news:12zsfnc0t7lua.1wbg7upo8ws6s$.dlg@40tude.net...
>>>> I haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc....
>>> 
>>> This:
>>> 
>>> (a < b) ? (a) : (b) = 15;
>>> 
>>> Would be the same as:
>>> 
>>> if(a < b)
>>>     a = 15;
>>> else
>>>     b = 15;
>>> 
>>> So it's using the ?: to select the destination of the assignment instead of the source.
>>
>>Okay, so the general form would be ...
>>
>>  (BooleanExpression) ? (Identifier1) : (Identifier2) = Expression;
>>
>>which would be equivalent to  ...
>>
>>   { // Start a scoping block.
>>     Typeof(Expression) Temp = Expression;
>>     if (BooleanExpression == true)
>>       Identifier1 = Temp;
>>     else
>>       Identifier2 = Temp;
>>   }
> 
> Yes.
> 
> Now consider to write 5 successive scopes and compare it with the ?: notation.

I was not making *any* judgment on the idea. I was only trying to gain understanding.

-- 
Derek Parnell
Melbourne, Australia
15/09/2005 2:02:47 AM
September 14, 2005
On Wed, 14 Sep 2005 14:57:14 +0000 (UTC), Manfred Nowak wrote:

> Derek Parnell wrote:
> 
> [...]
>> Okay, so the general form would be ...
> [...]
>>      Typeof(Expression) Temp = Expression;
> [...]
> 
> No. Because, D has at least that discontinuity with overloaded functions.

What the hell does that mean?

I did say "equivalent" right? All I meant was that it would AS IF one created a temporary variable that had the same type as the expression and assigned the expression to that temporary. What has that got to do with overloaded functions?

-- 
Derek Parnell
Melbourne, Australia
15/09/2005 2:04:43 AM
September 15, 2005
Derek Parnell wrote:

[...]
>>> Okay, so the general form would be ...
>> [...]
>>>      Typeof(Expression) Temp = Expression;
[...]
> I did say "equivalent" right? All I meant was that it would AS IF one created a temporary variable that had the same type as the expression and assigned the expression to that temporary.

Then I do not understand what you might mean with "as if".


> What has that got to do with overloaded functions?

If the RHS is the adress of an overloaded function `&f' then currently `typeof( &f)' has the type of the first definition of `f', which might be neither the type of the `?'-branch nor the type of the `:'-branch of the `?:'-operator. Therefore the general form is to take `typeof( LHS)' instead of `typeof( RHS)'.

-manfred

September 15, 2005
On Thu, 15 Sep 2005 05:32:29 +0000 (UTC), Manfred Nowak wrote:

> Derek Parnell wrote:
> 
> [...]
>>>> Okay, so the general form would be ...
>>> [...]
>>>>      Typeof(Expression) Temp = Expression;
> [...]
>> I did say "equivalent" right? All I meant was that it would AS IF one created a temporary variable that had the same type as the expression and assigned the expression to that temporary.
> 
> Then I do not understand what you might mean with "as if".
> 
>> What has that got to do with overloaded functions?
> 
> If the RHS is the adress of an overloaded function `&f' then currently `typeof( &f)' has the type of the first definition of `f', which might be neither the type of the `?'-branch nor the type of the `:'-branch of the `?:'-operator. Therefore the general form is to take `typeof( LHS)' instead of `typeof( RHS)'.

Okay I get the confusion now. When I said "Typeof(Expression)" I did not actually mean that we would use the D typeof() function. It was just my attempt at using shorthand to say 'whatever the type of the Expression is, we would use the exact same type for the temporary variable'.

Here it is in code, which should remove some confusion...

<code>
real foo(char a, short b)
{
   return 10.0L;
}

real foo(int a, long b)
{
   return 20.0L;
}

void main()
{
    typedef real function(int, long) r_foo_i_l;
    r_foo_i_l d;
    r_foo_i_l e;
    int a = 1;
    int b = 3;

    // Implementing ((a<b) ? (d) : (e) = &foo);
    {
    r_foo_i_l temp = &foo;

    if (a<b)
      d = temp;
    else
      e = temp;
    }
    assert( d !is null );
    assert( d(1, 2L) == 20.0L );
}
</code>

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
15/09/2005 3:39:40 PM
September 15, 2005
>> reason:
>> Limit code duplication and use of temporary variables in order to reduce
>> the bug-proneness of complex evaluations.
> 
> You can do
> 
>     *((a > b) ? (&a) : (&b)) = a*b + (b << 1) - (a >> 1) * (a & b);

To Stewart: Cool!

To OP:

This is all very nice.

But honestly, I don't see how this could possibly alleviate "bug-proneness".

Number one rule of avoiding bugs is: write clear code.

Number two is: Keep It Simple, Stupid.

Number three: But not any simpler than that.

Considering all this, I can't recommend the above style to anybody. Ideally, code should be written so that what it does is immediately visible, at first sight. One should also remember that many local temporary variables never get compiled into code. They are there only to make the programmer's intentions explicit -- and the compiler knows that.

At the same time, the compiled code may contain temporary variables not invented by the programmer (mostly in registers and the stack). For example, in the above code, the variable "a" is evaluated several times: chances are the compiled code only evaluates it once, and uses this (locally temporarily stored) value instead.

It is usual to find "optimisations" in program code, especially written by folks in "the C mindset". In the old times, when the compilers were simpler, the written code pretty much got compiled "as is". And that was okay, since C was essentially a "machine independent high level assembly language". Today we are going away from that -- even with C compilers. (Which means "what you write is what you get" is becoming history.) Code clarity and simplicity are much more valuable than stealing a few clock cycles or bytes, and smart compilers do that better than the programmer anyway.
September 15, 2005
Derek Parnell wrote:

[...]
> When I said "Typeof(Expression)" I
> did not actually mean that we would use the D typeof() function.
[...]

I understand now. Thank you.

-manfred