August 19, 2012
On 8/19/2012 5:08 AM, bearophile wrote:
> With a different type system the compiler makes sure at compile-time that x is
> not empty (this means the compiler makes sure in no code paths x is used before
> testing it contains something), avoiding the run-time exception.

That's called disabling the default constructor with @disable.


August 19, 2012
On 8/19/2012 4:48 AM, Peter Alexander wrote:
> Yes, I got this impression as well. What a sad state of affairs.

Yup. NaNs just don't get no respect, I tell ya! No respect at all!

August 19, 2012
On 08/17/2012 08:03 PM, Walter Bright wrote:
> Our discussion on this in the last few days inspired me to write a blog
> post about it:
>
> http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/
>
>
> http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723

Walter, I know you like to make the easy thing the right thing.  I like this notion myself.

So instead of writing

    float f;
    if (condition1)
        f = 7;
    ... code ...
    if (condition2)
        ++f;

is there any way we can make it easier to write

    void someCode() {
        ... code ...
    }

    float f;
    if ( condition )
    {
        f = 7;
        someCode();
        ++f;
    }
    else
        someCode();

assuming that condition2 is true when condition1 is true?

Maybe some other reasonable equivalent snippet could be concocted that's easier to discover, and make the language hint in that direction.

I feel like NaNs are a step forward, but better can be done.  They allow error detection, but it's still merely runtime error detection, and worse yet, it's /non-local/ error detection.  NaNs can spread from function to function and end up in completely different parts of a program than the place they originated.  This causes debugging hell, just like null values.  It makes me think that non-nan-able floating point types would be very useful, at least as function arguments, so that calling code doesn't have to introduce extra checks for NaNs that are either lost cycles or forgotten entirely and bug-ridden.

I really wish we had a way of catching NaNs in the function or line where they happen, and not in completely distant parts of the code.
August 19, 2012

"Walter Bright"  wrote in message news:k0rhp5$2fud$2@digitalmars.com... 

On 8/19/2012 4:48 AM, Peter Alexander wrote:
> Yes, I got this impression as well. What a sad state of affairs.

Yup. NaNs just don't get no respect, I tell ya! No respect at all!

NaNs are the Rodney Dangerfield of D...
August 19, 2012
On Sun, 19 Aug 2012 22:18:37 +0200, Walter Bright <newshound2@digitalmars.com> wrote:

> On 8/19/2012 5:08 AM, bearophile wrote:
>> With a different type system the compiler makes sure at compile-time that x is
>> not empty (this means the compiler makes sure in no code paths x is used before
>> testing it contains something), avoiding the run-time exception.
>
> That's called disabling the default constructor with @disable.

Nope. What bearophile is talking about is something more akin to this,
I think:

Nullable!int a;

int x = a; // Compile-time error: a might be null!

if ( a ) {
   int y = a; // 's fine, we know it's not null.
}

-- 
Simen
August 19, 2012
On Sun, 19 Aug 2012 05:52:01 +0200, Walter Bright <newshound2@digitalmars.com> wrote:

> On 8/18/2012 8:31 PM, Adam D. Ruppe wrote:
>> enum BOOL {
>>     TRUE,
>>     FALSE,
>>     FILE_NOT_FOUND
>> }
>
> I used to work with digital electronics. There, "boolean" logic actually had 4 states:
>
>      True
>      False
>      Don't Know
>      Don't Care
>

Like someone on Reddit mentioned, VHDL has 9 boolean states:

'U': uninitialized. This signal hasn't been set yet.
'X': unknown. Impossible to determine this value/result.
'0': logic 0
'1': logic 1
'Z': High Impedance
'W': Weak signal, can't tell if it should be 0 or 1.
'L': Weak signal that should probably go to 0
'H': Weak signal that should probably go to 1
'-': Don't care.

-- 
Simen
August 19, 2012
On Sun, 19 Aug 2012 14:08:17 +0200, bearophile <bearophileHUGS@lycos.com> wrote:

> Walter Bright:
>
>> Oh come on. That's called a "user defined type."
>
> This D code compiles and it throws an "Enforcement failed" Exception at runtime:
>
> import std.typecons: Nullable;
> void main() {
>      Nullable!int x;
>      int y = x;
> }
>
>
> With a different type system the compiler makes sure at compile-time that x is not empty (this means the compiler makes sure in no code paths x is used before testing it contains something), avoiding the run-time exception.

We could define a Nullable!T that does not allow access to the payload
value, and only give that access inside a special function, like
pattern matching in other languages:

Nullable!int a;

int n = a.match!(
    (int x)  => x,
    (None n) => 0
);

-- 
Simen
August 19, 2012
On 8/19/2012 2:41 PM, Simen Kjaeraas wrote:
> Nullable!int a;
>
> int x = a; // Compile-time error: a might be null!
>
> if ( a ) {
>     int y = a; // 's fine, we know it's not null.
> }

You'd want the int to be the non-nullable type. You can do this with D's type system. Each state would be a different type, with user defined conversions between them.


August 19, 2012
On 8/19/2012 1:43 PM, Chad J wrote:
> So instead of writing
>
>      float f;
>      if (condition1)
>          f = 7;
>      ... code ...
>      if (condition2)
>          ++f;
>
> is there any way we can make it easier to write
>
>      void someCode() {
>          ... code ...
>      }
>
>      float f;
>      if ( condition )
>      {
>          f = 7;
>          someCode();
>          ++f;
>      }
>      else
>          someCode();
>
> assuming that condition2 is true when condition1 is true?

Yes, you can do that.


> I feel like NaNs are a step forward, but better can be done.  They allow error
> detection, but it's still merely runtime error detection, and worse yet, it's
> /non-local/ error detection.  NaNs can spread from function to function and end
> up in completely different parts of a program than the place they originated.
> This causes debugging hell, just like null values.

I'm sorry, it's not debugging hell. I've done an awful lot of "figure out where this null came from" and it's a bit tedious, but not hell. You go step by step, such as "it's null in this function, so put an assert on the callers of the function", rinse, repeat.

Yes, I also know this is more of a problem if you've got a program that's not so easy to rerun.

> It makes me think that
> non-nan-able floating point types would be very useful, at least as function
> arguments, so that calling code doesn't have to introduce extra checks for NaNs
> that are either lost cycles or forgotten entirely and bug-ridden.

You can use signalling NaNs, if you like.


> I really wish we had a way of catching NaNs in the function or line where they
> happen, and not in completely distant parts of the code.

Nobody has even mentioned this until I brought it up, so I have a hard time believing the current state of affairs is a terrible problem that requires a major redesign to fix.

I know that nobody wants to see NaNs in their results, but be assured that that is far, far better than corrupted results that are off in subtle ways. NaNs are also one hell of a lot easier to track backwards than the other.
August 19, 2012
On 8/19/2012 8:18 AM, Peter Alexander wrote:
> Personally, I'd prefer option 1. Walter's argument is that this "leads to the
> programmer getting annoyed with false positive error diagnostics, and he'll
> likely add an =0", which is true, but in my opinion this scenario is quite rare
> to start with, and it's even more rare that 0 isn't actually the right
> initialisation value, and even then it's only a problem if the introduced bug is
> hard to reproduce.

Rare, yes, it's rare. But it's really ugly and hard to find when it does happen.

> I find it more likely that the NaN will go unnoticed and
> cause rare bugs.

NaNs in your output are pretty obvious. For example, if your accounting program prints "NAN" for the amount on the payroll cheques, someone is guaranteed to notice. But if it's a few cents off in your disfavor, it might take you years to discover there's a problem.

Critical systems also would find a NaN command a lot easier to detect than an off-by-two command, and would be able to shut down and engage the backup.