www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - float init 0 request

reply ABrightLight <example example.com> writes:
Hello. I understand this subject's been discussed a number of 
times before, but I'd like to throw in my reasoning for why it 
would benefit us more for floats to initialize to 0 than NaN.

1. float is generally used for numeric computation (things like 
NaN boxing are examples of uses outside of this) and as such have 
similarity to the integer types (they will even implicitly coerce 
mathematical operations to float). Since integers default to 0, 
floats should too.

1a. It may be argued that integers only default to 0 because 
there is no meaningful "null" value, but in my opinion this is 
not convincing because I think that most people would opt for 
them getting a reasonable default value right from the start 
instead of being forced to `= 0;` It is very common to see loop 
variables and other forms just say `int i;` or similar, and no 
one is confused by this.

2. It is argued that since, like pointers that have `null` and 
are default initialized to this, floats should also initialize to 
its version of `null`. However this is a false equivalence since 
the use of a null pointer is specified/standardized to crash the 
program due to a concern for memory safety (it's not even set to 
undefined behavior, a program halt must occur). The same memory 
safety concern is not present for most operations relying on 
floats, and the existence of NaN being left without a crash [or 
even an exception thrown] is to cater to performance. For cases 
where debugging by program halt is required, most of the time the 
approach done is for a compiler switch to allow throwing an 
exception instead of just halting the program, since a stack 
trace is presumed to be desired.

3. I know that rikki's DFA implementation will be able to detect 
when a `float x;` occurs without then being actually initialized 
to something useful (keep up the great work rikki!), but this 
particular feature is a special case that is not exactly within 
scope. And the fact that this is even being added as a special 
case should be a hint that leaving NaN as the default init is 
much less useful than some integer-compatible value like 0.

P.S. This subject is a bit subjective (no pun intended) but 
overall we'd likely see more user satisfaction from the float 
init switch. And from what I could tell, it's been well received 
by the OpenD folks, so there's already been a bit of a testbed 
for this.
Aug 13
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Floats are default initialized to NaN so people will be coerced to explicitly 
code what they want the initialized value to be.

I've seen enough code where the programmer forgot to initialize a float, it was 
defaulted to 0, and the wrong result was not detected.

```d
float f;     // code reviewer: did the programmer intend it to be 0?
float g = 0; // code reviewer: yes, the programmer likely meant to initialize
it 
to 0
```

It's similar to pointers being default initialized to null. Trying to use a
null 
pointer will result in a seg fault.

Most people decry this, but it's actually a great feature. If there's a bug in 
the code, it's better to find it sooner rather than after you ship.
Aug 13
next sibling parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced 
 to explicitly code what they want the initialized value to be.

 I've seen enough code where the programmer forgot to initialize 
 a float, it was defaulted to 0, and the wrong result was not
Why not make it an error, a float that is not explicitly initialized? Would be way better than implicit nan initialization, right?
Aug 14
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, August 14, 2026 1:05:06 AM Mountain Daylight Time Alexandru
Ermicioi via Digitalmars-d wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced
 to explicitly code what they want the initialized value to be.

 I've seen enough code where the programmer forgot to initialize
 a float, it was defaulted to 0, and the wrong result was not
Why not make it an error, a float that is not explicitly initialized? Would be way better than implicit nan initialization, right?
The language relies on the ability to default-initialize objects. For instance, that's what happens when you allocate a dynamic array or increase its length. There has to be a default value for that to work. It's part of why adding the ability to disable default initialization for structs has been a mess. It's arguably necessary for some contexts, but it means that those structs can't legally be used in any context where default initialization is required. Doing the same to floating point types would be even worse given that they're a built-in type rather than something specific to a particular code base. Also, languages like Java where they make it illegal to use a variable before you give it a value show how problematic it can be to make it an error to not explicitly initialize a variable, because it's pretty easy to get into situations where you know for sure that the variable is given a value before it's used, but the compiler isn't smart enough to figure that out, so you're forced to give it a dummy value just to shut it up. D's approach of having all types have a default value is just cleaner and simpler overall. It does kind of suck with regards to NaN, but the problems with NaN largely exist because NaN exists at all, which goes way beyond the issue of default initialization, and there's no getting around those issues, because NaN is a standard part of IEEE floating point types. - Jonathan M Davis
Aug 14
next sibling parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Friday, 14 August 2026 at 08:09:45 UTC, Jonathan M Davis wrote:
 The language relies on the ability to default-initialize 
 objects. For instance, that's what happens when you allocate a 
 dynamic array or increase its length. There has to be a default 
 value for that to work. It's part of why adding the ability to 
 disable default initialization for structs has been a mess. 
 It's arguably necessary for some contexts, but it means that 
 those structs can't legally be used in any context where 
 default initialization is required. Doing the same to floating 
 point types would be even worse given that they're a built-in 
 type rather than something specific to a particular code base.
Right, that would cause mayhem in templated code, an extra static if at minimum.
 Also, languages like Java where they make it illegal to use a 
 variable before you give it a value show how problematic it can 
 be to make it an error to not explicitly initialize a variable, 
 because it's pretty easy to get into situations where you know 
 for sure that the variable is given a value before it's used, 
 but the compiler isn't smart enough to figure that out, so 
 you're forced to give it a dummy value just to shut it up.
Nowadays java compiler seems smarter, it doesn't force you initialize it at declaration site, if all branches after declaration get var initialized before its use.
Aug 14
next sibling parent reply Indraj Gandham <newsgroups indraj.net> writes:
On Friday, 14 August 2026 at 10:42:16 UTC, Alexandru Ermicioi 
wrote:
 On Friday, 14 August 2026 at 08:09:45 UTC, Jonathan M Davis 
 wrote:
 The language relies on the ability to default-initialize 
 objects. For instance, that's what happens when you allocate a 
 dynamic array or increase its length. There has to be a 
 default value for that to work. It's part of why adding the 
 ability to disable default initialization for structs has been 
 a mess. It's arguably necessary for some contexts, but it 
 means that those structs can't legally be used in any context 
 where default initialization is required. Doing the same to 
 floating point types would be even worse given that they're a 
 built-in type rather than something specific to a particular 
 code base.
Right, that would cause mayhem in templated code, an extra static if at minimum.
This is a valid point, but it merely implies that there should be a default initialisation value. It does not imply that this value must be NaN. It's worth noting that the proposed change was implemented in OpenD and there have been very few complaints. If correctness is the goal, the way forward is static analysis, not an "error" value which doesn't actually trigger any sort of error handling or exception.
Aug 14
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 5:48 AM, Indraj Gandham wrote:
 It's worth noting that the proposed change was implemented in OpenD
That's a mistake.
 and there have been very few complaints.
All it takes is one unintentional default initialization of 0.0 which leads to a subtle bug in your avionics code, banking software, I-beam design, data analysis, etc. And yes, I have seen cases were a linter complained about lack of an initializer on C code, and the maintainer inserted "=0" which closed the issue, but introduced a bug. The idea is to make such bugs OBVIOUS, not subtle.
Aug 14
next sibling parent Mindy Batek (0xEAB) <desisma heidel.beer> writes:
On Friday, 14 August 2026 at 17:40:20 UTC, Walter Bright wrote:
 All it takes is one unintentional default initialization of 0.0 
 which leads to a subtle bug in your avionics code, banking 
 software, I-beam design, data analysis, etc.
For graphic applications, it can lead to a minor detail not getting rendered, which in turn can be just as subtle as a math error. The assumption that a single NaN would poison the whole output only holds for numeric calculations where all data is eventually accumulated into one atomic data pool as part of a single (large) formula.
 The idea is to make such bugs OBVIOUS, not subtle.
I suspect that would require SIGNALING NaNs.
Aug 14
prev sibling parent claptrap <clap trap.com> writes:
On Friday, 14 August 2026 at 17:40:20 UTC, Walter Bright wrote:
 On 8/14/2026 5:48 AM, Indraj Gandham wrote:

 And yes, I have seen cases were a linter complained about lack 
 of an initializer on C code, and the maintainer inserted "=0" 
 which closed the issue, but introduced a bug.
You haven't solved this problem, the guy who sees an uninitialized float and inserts a zero, will do exactly the same when he sees a default initialized float. He'll lob a zero in, compile and run and see if it's "fixed". Default to NaN doesn't fix that.
Aug 15
prev sibling next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 14/08/2026 10:42 PM, Alexandru Ermicioi wrote:
     Also, languages like Java where they make it illegal to use a
     variable before you give it a value show how problematic it can be
     to make it an error to not explicitly initialize a variable, because
     it's pretty easy to get into situations where you know for sure that
     the variable is given a value before it's used, but the compiler
     isn't smart enough to figure that out, so you're forced to give it a
     dummy value just to shut it up.
 
 Nowadays java compiler seems smarter, it doesn't force you initialize it 
 at declaration site, if all branches after declaration get var 
 initialized before its use.
This only works without false positives in limited cases. The moment pointers are involved, loops, or functions it basically error central. The fast dfa engine has to ignore any variable that is in a closure context specifically because it can't be modeled. Which is a bit of a problem for us, see unreachable code error for why it isn't a good by default bit of analysis.
Aug 14
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 3:42 AM, Alexandru Ermicioi wrote:
 Nowadays java compiler seems smarter, it doesn't force you initialize it at 
 declaration site, if all branches after declaration get var initialized before 
 its use.
This requires Data Flow Analysis, which slows the compiler down. It's not a good idea to have the semantics change when turning the optimizer on. Note that when the optimizer is run on D code, any redundant NaN initialization gets removed, so there is no penalty for default initialization. (It's called "Dead Assignment Removal".)
Aug 14
prev sibling parent claptrap <clap trap.com> writes:
On Friday, 14 August 2026 at 08:09:45 UTC, Jonathan M Davis wrote:
 On Friday, August 14, 2026 1:05:06 AM Mountain Daylight Time 
 Alexandru Ermicioi via Digitalmars-d wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be 
 coerced to explicitly code what they want the initialized 
 value to be.

 I've seen enough code where the programmer forgot to 
 initialize a float, it was defaulted to 0, and the wrong 
 result was not
Why not make it an error, a float that is not explicitly initialized? Would be way better than implicit nan initialization, right?
The language relies on the ability to default-initialize objects. For instance, that's what happens when you allocate a dynamic array or increase its length.
Make it an error where it can be detected, for fields and locals. And make it NaN for expanding arrays. That would be more useful than the current situation.
Aug 15
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 12:05 AM, Alexandru Ermicioi wrote:
 Why not make it an error, a float that is not explicitly initialized? Would be 
 way better than implicit nan initialization, right?
Because then you wind up with: ```d float f = 0; // shut up the spurious compiler error message ... initialize(&f); // the actual initialization ``` The 0 initialization is inserted to shut up the compiler, and it will take the reviewer a bit of time wondering why f was initialized to the wrong value. In other words, redundant/vacuous assignments are a code smell. It's a small point, but D is an elegant language, and requiring people to write smelly code is not elegant.
Aug 14
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 15/08/2026 5:26 AM, Walter Bright wrote:
 On 8/14/2026 12:05 AM, Alexandru Ermicioi wrote:
 Why not make it an error, a float that is not explicitly initialized? 
 Would be way better than implicit nan initialization, right?
Because then you wind up with: ```d float f = 0; // shut up the spurious compiler error message ... initialize(&f); // the actual initialization ``` The 0 initialization is inserted to shut up the compiler, and it will take the reviewer a bit of time wondering why f was initialized to the wrong value. In other words, redundant/vacuous assignments are a code smell. It's a small point, but D is an elegant language, and requiring people to write smelly code is not elegant.
Alternatively make the parameter out: ```d void initialize(out float v); float f; initialize(f); ```
Aug 14
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 10:28 AM, Richard (Rikki) Andrew Cattermole wrote:
 Alternatively make the parameter out:
 
 ```d
 void initialize(out float v);
 
 float f;
 
 initialize(f);
 ```
`out` will default initialize `v` to NaN upon entry to the function!
Aug 14
prev sibling next sibling parent claptrap <clap trap.com> writes:
On Friday, 14 August 2026 at 17:26:04 UTC, Walter Bright wrote:
 On 8/14/2026 12:05 AM, Alexandru Ermicioi wrote:
 Why not make it an error, a float that is not explicitly 
 initialized? Would be way better than implicit nan 
 initialization, right?
Because then you wind up with: ```d float f = 0; // shut up the spurious compiler error message ... initialize(&f); // the actual initialization ``` The 0 initialization is inserted to shut up the compiler, and it will take the reviewer a bit of time wondering why f was initialized to the wrong value. In other words, redundant/vacuous assignments are a code smell. It's a small point, but D is an elegant language, and requiring people to write smelly code is not elegant.
And yet that is exactly what you have the compiler doing, inserting a spurious redundant assignment by default, it's just as smelly.
Aug 15
prev sibling parent Riven <riven baryonides.ru> writes:
On Friday, 14 August 2026 at 17:26:04 UTC, Walter Bright wrote:

 The 0 initialization is inserted to shut up the compiler, and 
 it will take the reviewer a bit of time wondering why f was 
 initialized to the wrong value.
So: Variables must be initialized (1) with the correct initial values (1). If the compiler outputs an error saying "variable not initialized" the programmer will fix this error mechanically (initialize the variable with the first "correct" value that comes to mind, most likely 0.0). If the compiler politely remains silent but initializes the variable with a default value that will most likely lead to an incorrect result, the programmer will notice the bug and be forced to find the correct initial value to fix it. A dirty manipulation :-) ingenious though. What about integers? Why not initialize it with .max? Or some prime number?
Aug 15
prev sibling next sibling parent reply Indraj Gandham <newsgroups indraj.net> writes:
On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 It's similar to pointers being default initialized to null. 
 Trying to use a null pointer will result in a seg fault.
It's not similar at all. There is no sensible init value for a pointer but there is for a float. This change would bring more consistency within D with regard to the behaviour of numeric types. It would also bring D in line with what other languages do (and what most programmers likely expect).
 Most people decry this, but it's actually a great feature. If 
 there's a bug in the code, it's better to find it sooner rather 
 than after you ship.
It's better to find it at compile time and emit a warning, as in Rust. The NaN value silently propagates and is therefore the worst possible choice.
Aug 14
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 14 August 2026 at 08:17:41 UTC, Indraj Gandham wrote:
 There is no sensible init value for a pointer
There is, especially for a gc language; theres at least 3 great options new innate last matching type on the stack
Aug 14
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 1:17 AM, Indraj Gandham wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 It's similar to pointers being default initialized to null. Trying to use a 
 null pointer will result in a seg fault.
It's not similar at all. There is no sensible init value for a pointer but there is for a float.
I'm afraid we disagree. The null pointer initialization ensures that you cannot dereference an uninitialized pointer and not find out about it. Getting a "NaN" in your program's output is sure to notify the user that there is a BUG in the program. Default initializing to 0.0 runs the high risk of the bug not being noticed.
 This change would bring more consistency within D with regard to 
 the behaviour of numeric types. It would also bring D in line with what other 
 languages do (and what most programmers likely expect).
This is why D is better than other languages.
 Most people decry this, but it's actually a great feature. If there's a bug in 
 the code, it's better to find it sooner rather than after you ship.
It's better to find it at compile time and emit a warning, as in Rust.
Consider a scientist setting out an array of data collection sensors. If you've got a lot of them, inevitably some will be bad. A bad one should not bring down the whole system. Having the bad data replaced with NaN will mean the rest of your array data will not be corrupted by a stuck-at-zero problem with one sensor.
 The NaN value silently propagates and is therefore the worst possible choice.
The worst possible choice is the maintainer shutting up the compiler and initializing it to 0.0 without checking what the correct value should be. And you may never realize that this 0.0 propagated into your output. Yes, this happens. I've seen it happen. Having a NaN in your output tells you that your code is broken. A default 0.0 hides bugs.
Aug 14
next sibling parent Mindy Batek (0xEAB) <desisma heidel.beer> writes:
On Friday, 14 August 2026 at 17:54:25 UTC, Walter Bright wrote:
 The worst possible choice is the maintainer shutting up the 
 compiler and initializing it to 0.0 without checking what the 
 correct value should be.
This is, unironically, a surprisingly accurate description of the average DIP1000 user experience with return ref scope attributes.
Aug 14
prev sibling next sibling parent reply claptrap <clap trap.com> writes:
On Friday, 14 August 2026 at 17:54:25 UTC, Walter Bright wrote:
 On 8/14/2026 1:17 AM, Indraj Gandham wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 It's similar to pointers being default initialized to null. 
 Trying to use a null pointer will result in a seg fault.
It's not similar at all. There is no sensible init value for a pointer but there is for a float.
I'm afraid we disagree. The null pointer initialization ensures that you cannot dereference an uninitialized pointer and not find out about it. Getting a "NaN" in your program's output is sure to notify the user that there is a BUG in the program. Default initializing to 0.0 runs the high risk of the bug not being noticed.
It's not a guarantee though is it. NaN is a valid result of some mathematical operations, so an "uninitialized float NaN" could still get lost or hidden. Heck converting a float to integer and the NaN is gone. You need to stop acting like it's foolproof, it's really not. Actually making initialized floats an error would be far more useful.
 Consider a scientist setting out an array of data collection 
 sensors. If you've got a lot of them, inevitably some will be 
 bad. A bad one should not bring down the whole system. Having 
 the bad data replaced with NaN will mean the rest of your array 
 data will not be corrupted by a stuck-at-zero problem with one 
 sensor.
Nonsense. "Data collection sensors" don't use floating point. Why the hell would they add all the silicon overhead of floating point to a sensor IC? They use ints, I've literally never seen a floating point one.
 The NaN value silently propagates and is therefore the worst
possible choice. The worst possible choice is the maintainer shutting up the compiler and initializing it to 0.0 without checking what the correct value should be. And you may never realize that this 0.0 propagated into your output. Yes, this happens. I've seen it happen. Having a NaN in your output tells you that your code is broken. A default 0.0 hides bugs.
99 times out of 100 0.0 is the correct value. So is the 1 time in 100 that NaN helps error early worth the other 99 times you get a NaN nowhere near where it actually comes from? Its not as clear cut as you claim it to be.
Aug 15
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/15/2026 3:07 AM, claptrap wrote:
 You need to stop acting like it's foolproof, it's really not.
You are correct that it is not foolproof, but it is far better than 0, because the error is far more likely to be detected.
Aug 19
prev sibling next sibling parent reply Indraj Gandham <newsgroups indraj.net> writes:
On Friday, 14 August 2026 at 17:54:25 UTC, Walter Bright wrote:
 I'm afraid we disagree. The null pointer initialization ensures 
 that you cannot dereference an uninitialized pointer and not 
 find out about it. Getting a "NaN" in your program's output is 
 sure to notify the user that there is a BUG in the program. 
 Default initializing to 0.0 runs the high risk of the bug not 
 being noticed.
The difference is that the null ptr will always cause your program to crash when you try to use it. The NaN value will not, and unless your program prints out every float (or you use contracts) it will often be difficult to track down the cause of any resulting strange behaviour. This is the heart of the issue: if you remembered to initialise the float, put in a contract or print the value, you probably also remembered about the default NaN. But if you didn't, it's more likely you wanted 0.0 than NaN. In fact, NaN is almost guaranteed to be incorrect, and it'll appear in the places you least expect.
 This is why D is better than other languages.
D has many facets which make it the best programming language in the world. This is not one of them.
 Consider a scientist setting out an array of data collection 
 sensors. If you've got a lot of them, inevitably some will be 
 bad. A bad one should not bring down the whole system. Having 
 the bad data replaced with NaN will mean the rest of your array 
 data will not be corrupted by a stuck-at-zero problem with one 
 sensor.
This is a contrived example. There are far better, well-understood and widely-known anomaly detection techniques the scientist could leverage to flag (and remove) faulty sensor data before it is processed.
 The worst possible choice is the maintainer shutting up the 
 compiler and initializing it to 0.0 without checking what the 
 correct value should be. And you may never realize that this 
 0.0 propagated into your output. Yes, this happens. I've seen 
 it happen.
(1) The D compiler does not emit a warning before default NaN initialisation. (2) You're saying it wouldn't be enough anyway, as the user would ignore this imaginary warning and would write `= 0` just to shut it up. It appears you are making the argument that instead of warning the user about incorrect behaviour at compile-time, and instead of inserting the value that the user likely wanted, you are going to make them track down garbage at runtime on the off-chance that they didn't want 0.0 I hope this is a misunderstanding.
Aug 17
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/17/2026 5:59 AM, Indraj Gandham wrote:
 it's more likely you wanted 0.0 than NaN. In fact, NaN 
 is almost guaranteed to be incorrect
And that is exactly the point of NaN - to be incorrect, and to stand out like a rock in your shoe.
 D has many facets which make it the best programming language in the world.
This 
 is not one of them.
Consider the two options: 1. default initialize to 0, because that will be correct most of the time. Never mind if the flight computer says 18,000 gallons of gas is needed to cross the Atlantic, when 20,000 is actually needed. But 18,000 looks good, and you take off, get past the halfway point, and fall out of the sky. 2. default initialize to NaN, and your flight computer says you need NaN gallons of gas, and you turn around and go immediately back to the gate. Option 2 is better when writing professional quality software. --- I googled "software catastrophe caused by incorrect zero initialization" and got: "A software catastrophe caused by incorrect zero initialization often relates to uninitialized memory defaulting to zero unexpectedly, or conversely, a critical variable failing to be zeroed out or handling a zero value improperly (such as a division-by-zero or arithmetic counter rollover). A famous analogue is the September 1997 incident on the guided-missile cruiser USS Yorktown, where a crew member entered a 0 into a database field, causing a division-by-zero collapse across the ship's propulsion network."
Aug 19
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Thursday, 20 August 2026 at 03:36:33 UTC, Walter Bright wrote:
 On 8/17/2026 5:59 AM, Indraj Gandham wrote:
 it's more likely you wanted 0.0 than NaN. In fact, NaN is 
 almost guaranteed to be incorrect
And that is exactly the point of NaN - to be incorrect, and to stand out like a rock in your shoe.
 D has many facets which make it the best programming language 
 in the world. This is not one of them.
Consider the two options: 1. default initialize to 0, because that will be correct most of the time. Never mind if the flight computer says 18,000 gallons of gas is needed to cross the Atlantic, when 20,000 is actually needed. But 18,000 looks good, and you take off, get past the halfway point, and fall out of the sky.
This contrived almost impossible to occur scenario where zero somehow equates to a factor of 2000 which was not caught in testing is not convincing.
 2. default initialize to NaN, and your flight computer says you 
 need NaN gallons of gas, and you turn around and go immediately 
 back to the gate.
I can play too: ```d if(gas < amountNeeded) warnPilot(); ``` -Steve
Aug 20
parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 21 August 2026 at 02:36:38 UTC, Steven Schveighoffer 
wrote:
 1. default initialize to 0, because that will be correct most 
 of the time. Never mind if the flight computer says 18,000 
 gallons of gas is needed to cross the Atlantic, when 20,000 is 
 actually needed. But 18,000 looks good, and you take off, get 
 past the halfway point, and fall out of the sky.
This contrived almost impossible to occur scenario where zero somehow equates to a factor of 2000 which was not caught in testing is not convincing.
Airplane surgery is very complicated.
Aug 20
prev sibling parent Mindy Batek (0xEAB) <desisma heidel.beer> writes:
On Friday, 14 August 2026 at 17:54:25 UTC, Walter Bright wrote:
 Consider a scientist setting out an array of data collection 
 sensors. If you've got a lot of them, inevitably some will be 
 bad. A bad one should not bring down the whole system. Having 
 the bad data replaced with NaN will mean the rest of your array 
 data will not be corrupted by a stuck-at-zero problem with one 
 sensor.
But NaN as default init value is not like a defective sensor distorting the output with bad data. It is like a flawed sensor design always feeding the system with bad data because of a design failure in its circuitry.
Aug 17
prev sibling next sibling parent reply ABrightLight <example example.com> writes:
On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced 
 to explicitly code what they want the initialized value to be.

 I've seen enough code where the programmer forgot to initialize 
 a float, it was defaulted to 0, and the wrong result was not 
 detected.

 ```d
 float f;     // code reviewer: did the programmer intend it to 
 be 0?
 float g = 0; // code reviewer: yes, the programmer likely meant 
 to initialize it to 0
 ```

 It's similar to pointers being default initialized to null. 
 Trying to use a null pointer will result in a seg fault.

 Most people decry this, but it's actually a great feature. If 
 there's a bug in the code, it's better to find it sooner rather 
 than after you ship.
Hi Walter, I really appreciate the response, however I think that all the points I wrote were unaddressed (I mentioned the comparison with null pointers and why it is my opinion that it is a false equivalence as well). Nevertheless, the topic is relatively low importance to me and I'm okay with just using a linter to remind myself to explicitly initialize the floats. I just figured the change would be an easy QOL improvement for most users. With regards to erroring if they're not initialized, that would be a very good alternative to 0 init as well (I mentioned that too).
Aug 14
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 14/08/2026 8:19 PM, ABrightLight wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced to 
 explicitly code what they want the initialized value to be.

 I've seen enough code where the programmer forgot to initialize a 
 float, it was defaulted to 0, and the wrong result was not detected.

 ```d
 float f;     // code reviewer: did the programmer intend it to be 0?
 float g = 0; // code reviewer: yes, the programmer likely meant to 
 initialize it to 0
 ```

 It's similar to pointers being default initialized to null. Trying to 
 use a null pointer will result in a seg fault.

 Most people decry this, but it's actually a great feature. If there's 
 a bug in the code, it's better to find it sooner rather than after you 
 ship.
Hi Walter, I really appreciate the response, however I think that all the points I wrote were unaddressed (I mentioned the comparison with null pointers and why it is my opinion that it is a false equivalence as well).
Unfortunately this is a good example of Walter leaving out the analysis, and skipping to the conclusion. I spend a good chunk of my time figuring out what the analysis was lol. NaN's come in two flavors, signaling and non-signaling. Originally D default initialized floats to signal, but that was changed as it was producing an inconsistency that was a problem (I wasn't involved with this). If you try to do math on a signaling NaN it will throw a hardware exception, just like doing a null dereference does. A non-signaling NaN is good, because you can at least detect when something has gone wrong, just not the source. Silent corruption is always worse than detectable corruption.
 Nevertheless, the topic is relatively low importance to me and I'm okay 
 with just using a linter to remind myself to explicitly initialize the 
 floats. I just figured the change would be an easy QOL improvement for 
 most users.
https://forum.dlang.org/thread/tcfqveygmebplsgmexgr forum.dlang.org
Aug 14
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 7:02 AM, Richard (Rikki) Andrew Cattermole wrote:
 NaN's come in two flavors, signaling and non-signaling.
 
 Originally D default initialized floats to signal, but that was changed as it 
 was producing an inconsistency that was a problem (I wasn't involved with
this).
Signalling NaNs simply did not work unless you wrote your code in assembler. That's because the compiler itself would flip it to a quiet nan every time it was copied.
 If you try to do math on a signaling NaN it will throw a hardware exception, 
 just like doing a null dereference does.
No compiler I know implements this, because it's a nuisance. NaNs were invented for the 8087, and while it made sense on paper, in practice it didn't work out too well.
 A non-signaling NaN is good, because you can at least detect when something
has 
 gone wrong, just not the source.
 
 Silent corruption is always worse than detectable corruption.
We can agree on that!
Aug 14
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 15/08/2026 9:28 AM, Walter Bright wrote:
     A non-signaling NaN is good, because you can at least detect when
     something has gone wrong, just not the source.
 
     Silent corruption is always worse than detectable corruption.
 
 We can agree on that!
The only thing you and I disagree on for NaN's is how much static analysis to throw at it. Personally I'm all for throwing full soundness at it!
Aug 14
prev sibling parent claptrap <clap trap.com> writes:
On Friday, 14 August 2026 at 21:28:54 UTC, Walter Bright wrote:
 On 8/14/2026 7:02 AM, Richard (Rikki) Andrew Cattermole wrote:

 If you try to do math on a signaling NaN it will throw a 
 hardware exception, just like doing a null dereference does.
No compiler I know implements this, because it's a nuisance. NaNs were invented for the 8087, and while it made sense on paper, in practice it didn't work out too well.
The old Delphi compiler did, backing the 2000s, no idea if it still does. But you did have to be careful interfacing with external code, like calling C++ dll you had to make sure to switch it off and back on again. It was actually pretty useful from what i remember.
Aug 15
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 1:19 AM, ABrightLight wrote:
 Hi Walter, I really appreciate the response, however I think that all the
points 
 I wrote were unaddressed (I mentioned the comparison with null pointers and
why 
 it is my opinion that it is a false equivalence as well).
My opinion is it is a reasonable equivalence! Both are meant to make errors visible.
 With regards to erroring if they're not initialized, that would be a very good 
 alternative to 0 init as well (I mentioned that too).
I responded to that multiple times :-/
Aug 14
parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 14 August 2026 at 21:24:36 UTC, Walter Bright wrote:
 On 8/14/2026 1:19 AM, ABrightLight wrote:
 Hi Walter, I really appreciate the response, however I think 
 that all the points I wrote were unaddressed (I mentioned the 
 comparison with null pointers and why it is my opinion that it 
 is a false equivalence as well).
My opinion is it is a reasonable equivalence! Both are meant to make errors visible.
 With regards to erroring if they're not initialized, that 
 would be a very good alternative to 0 init as well (I 
 mentioned that too).
I responded to that multiple times :-/
recently trump said "house prices should go up"; that may in fact be `a response` but perhaps some people may feel `unaddressed`
Aug 14
prev sibling next sibling parent An <home home.com> writes:
On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced 
 to explicitly code what they want the initialized value to be.

 I've seen enough code where the programmer forgot to initialize 
 a float, it was defaulted to 0, and the wrong result was not 
 detected.

 ```d
 float f;     // code reviewer: did the programmer intend it to 
 be 0?
 float g = 0; // code reviewer: yes, the programmer likely meant 
 to initialize it to 0
 ```
D advocates for unittest -> what happen to it? Same as int i; // There is no different than float -> be consistent Happy Coding!
Aug 14
prev sibling next sibling parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced 
 to explicitly code what they want the initialized value to be.
Maybe the next D Edition could require initialization of types that don’t initialize with a value equal to `0`. D’s behavior with these is annoying, because leads to needless debug sessions, and also surprising because no other language that D is similar Essentially, character and floating-point types should behave like structs with ` disable this()`. Of course, as I said, that would be for the next Edition because it would break code. I don’t know how much existing D code really uses those initializers, probably some, but very little, because the defaults are quite useless, intentionally so.
Aug 17
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 18/08/2026 2:03 AM, Quirin Schroll wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced to 
 explicitly code what they want the initialized value to be.
Maybe the next D Edition could require initialization of types that don’t initialize with a value equal to `0`. D’s behavior with these is annoying, because leads to needless debug sessions, and also surprising Java all default-initialize to `0`. Essentially, character and floating- point types should behave like structs with ` disable this()`. Of course, as I said, that would be for the next Edition because it would break code. I don’t know how much existing D code really uses those initializers, probably some, but very little, because the defaults are quite useless, intentionally so.
Just keep in mind that this cannot cover all cases, like heap allocations.
Aug 17
prev sibling next sibling parent reply libxmoc <libxmoc gmail.com> writes:
On Monday, 17 August 2026 at 14:03:46 UTC, Quirin Schroll wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be 
 coerced to explicitly code what they want the initialized 
 value to be.
Maybe the next D Edition could require initialization of types that don’t initialize with a value equal to `0`. D’s behavior with these is annoying, because leads to needless debug sessions, and also surprising because no other language that D default-initialize to `0`. Essentially, character and floating-point types should behave like structs with ` disable this()`. Of course, as I said, that would be for the next Edition because it would break code. I don’t know how much existing D code really uses those initializers, probably some, but very little, because the defaults are quite useless, intentionally so.
I don't think it's wise to change, it'll cause too much friction and inconsistency in documentation, however, I think there is something that could be done as a compromise. extern(C) struct was rejected, so perhaps a ` pod struct` that ensures 0 init would be better? 0 init has the advantage of producing tiny executable, so there are still some valid reason to have them.
Aug 17
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 17 August 2026 at 14:16:58 UTC, libxmoc wrote:
 0 init has the advantage of producing tiny executable, so there 
 are still some valid reason to have them.
This is actually what put me over the edge on making the change in opend. I'm basically on the fence, nan and 0 have pros and cons, but this is a little advantage. My blog about it btw: https://dpldocs.info/this-week-in-arsd/Blog.Posted_2025_09_29.html#float-and-char-init
Aug 17
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/17/2026 7:16 AM, libxmoc wrote:
 and also surprising because no other 

 default-initialize to `0`.
C and C++ still do not default initialize stack variables to anything other than garbage. before explicitly assigning a value, you get an error. (It's extremely difficult to track down an uninitialized variable in C and C++, because every change you make to the program to try and track it down, changes the values in it.)
Aug 17
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 18/08/2026 3:15 PM, Walter Bright wrote:
 (It's extremely difficult to track down an uninitialized variable in C 
 and C++, because every change you make to the program to try and track 
 it down, changes the values in it.)
-preview=fastdfa says otherwise. So many of the C tests fail due to this :)
Aug 17
prev sibling next sibling parent reply Indraj Gandham <newsgroups indraj.net> writes:
On Monday, 17 August 2026 at 14:03:46 UTC, Quirin Schroll wrote:
 Maybe the next D Edition could require initialization of types 
 that don’t initialize with a value equal to `0`. D’s behavior 
 with these is annoying, because leads to needless debug 
 sessions, and also surprising because no other language that D 

 default-initialize to `0`. Essentially, character and 
 floating-point types should behave like structs with ` disable 
 this()`.

 Of course, as I said, that would be for the next Edition 
 because it would break code. I don’t know how much existing D 
 code really uses those initializers, probably some, but very 
 little, because the defaults are quite useless, intentionally 
 so.
Very little code would be impacted, as shown by OpenD's successful change from NaN to 0.0, a small QoL improvement which could be implemented in upstream today (but won't be).
Aug 17
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 17 August 2026 at 14:43:00 UTC, Indraj Gandham wrote:
 [snip]

 Very little code would be impacted, as shown by OpenD's 
 successful change from NaN to 0.0, a small QoL improvement 
 which could be implemented in upstream today (but won't be).
"Small QoL improvement...could be implemented in upstream today" that would also potentially break code. This is what editions are for.
Aug 17
next sibling parent reply Indraj Gandham <newsgroups indraj.net> writes:
On Monday, 17 August 2026 at 18:23:32 UTC, jmh530 wrote:
 "Small QoL improvement...could be implemented in upstream 
 today" that would also potentially break code. This is what 
 editions are for.
You are referring to this change as if it is a hypothetical. In reality, it has already been done and the extent of the (limited) breakage has been assessed. See the link in adr's post for details.
Aug 17
parent reply Sergey <kornburn yandex.ru> writes:
On Monday, 17 August 2026 at 20:20:23 UTC, Indraj Gandham wrote:
 You are referring to this change as if it is a hypothetical. In 
 reality, it has already been done and the extent of the 
 (limited) breakage has been assessed. See the link in adr's 
 post for details.
Don't forget that OpenD has limited usage as well. And even though Adam's code base may be big - it is mostly written by Adam (with his habits). Upstream D may have much wider variety of code design usages.
Aug 17
parent monkyyy <crazymonkyyy gmail.com> writes:
On Monday, 17 August 2026 at 21:35:35 UTC, Sergey wrote:
 On Monday, 17 August 2026 at 20:20:23 UTC, Indraj Gandham wrote:
 You are referring to this change as if it is a hypothetical. 
 In reality, it has already been done and the extent of the 
 (limited) breakage has been assessed. See the link in adr's 
 post for details.
Don't forget that OpenD has limited usage as well. And even though Adam's code base may be big - it is mostly written by Adam (with his habits). Upstream D may have much wider variety of code design usages.
:spray_bottle: "You are referring to this change as if it is a hypothetical."
Aug 17
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Monday, 17 August 2026 at 18:23:32 UTC, jmh530 wrote:
 "Small QoL improvement...could be implemented in upstream 
 today" that would also potentially break code. This is what 
 editions are for.
My understanding is that an older edition will eventually stop being supported, and that the intent is at some point for old code to be ported to a newer edition if it needs to compile with a newer compiler. Changing `float.init` could cause errors that can only be detected at runtime, perhaps in some very rare combination of runtime events. I don't think D should (ab)use editions to silently break the runtime behaviour of code that was correct in an earlier version.
Aug 17
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Monday, 17 August 2026 at 20:50:39 UTC, Nick Treleaven wrote:
 My understanding is that an older edition will eventually stop 
 being supported, and that the intent is at some point for old 
 code to be ported to a newer edition if it needs to compile 
 with a newer compiler.
I don't think we are supposed to stop supporting any specific editions. That would defeat the purpose. -Steve
Aug 17
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 18/08/2026 2:36 PM, Steven Schveighoffer wrote:
 On Monday, 17 August 2026 at 20:50:39 UTC, Nick Treleaven wrote:
 My understanding is that an older edition will eventually stop being 
 supported, and that the intent is at some point for old code to be 
 ported to a newer edition if it needs to compile with a newer compiler.
I don't think we are supposed to stop supporting any specific editions. That would defeat the purpose. -Steve
Eventually we will, but it'll be like 20+ years.
Aug 17
prev sibling parent Nick Treleaven <nick geany.org> writes:
On Tuesday, 18 August 2026 at 02:36:59 UTC, Steven Schveighoffer 
wrote:
 On Monday, 17 August 2026 at 20:50:39 UTC, Nick Treleaven wrote:
 My understanding is that an older edition will eventually stop 
 being supported, and that the intent is at some point for old 
 code to be ported to a newer edition if it needs to compile 
 with a newer compiler.
I don't think we are supposed to stop supporting any specific editions. That would defeat the purpose.
Even if that were true, it should not be unreasonably hard to port old code to a newer edition.
Aug 19
prev sibling next sibling parent Dukc <ajieskola gmail.com> writes:
On Monday, 17 August 2026 at 14:03:46 UTC, Quirin Schroll wrote:
 On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be 
 coerced to explicitly code what they want the initialized 
 value to be.
Maybe the next D Edition could require initialization of types that don’t initialize with a value equal to `0`. D’s behavior with these is annoying, because leads to needless debug sessions, and also surprising because no other language that D default-initialize to `0`. Essentially, character and floating-point types should behave like structs with ` disable this()`.
When done well (like in Haskell or Rust) I also think the best default values are no default values. But that requires it's easy to avoid declaring variables before there are valid values for them. IMO it isn't the case in D. The language is imperative at its root so there are often cases where you want to declare a variable before initialising it. It is almost always possible to avoid doing so if you're dogged about it, but the cure tends to get worse at times than the disease. D-style "paranoid" default values are the best option IMO - at least for mundane types - when language ergonomics would suffer without them. If, with help of future language features, we can comprehensively avoid relying the default values some day without kludgy tricks, then it's time to do what you suggest.
Aug 17
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/17/2026 7:03 AM, Quirin Schroll wrote:
 Maybe the next D Edition could require initialization of types that don’t 
 initialize with a value equal to `0`. D’s behavior with these is annoying, 
 because leads to needless debug sessions, and also surprising because no other 

default-initialize 
 to `0`.
My reply to this seems to have disappeared. C and C++ default initialize locals to garbage, not zero. initializations.
Aug 19
parent reply Serg Gini <kornburn yandex.ru> writes:
On Wednesday, 19 August 2026 at 07:31:14 UTC, Walter Bright wrote:
 On 8/17/2026 7:03 AM, Quirin Schroll wrote:
 Maybe the next D Edition could require initialization of types 
 that don’t initialize with a value equal to `0`. D’s behavior 
 with these is annoying, because leads to needless debug 
 sessions, and also surprising because no other language that D 

 default-initialize to `0`.
My reply to this seems to have disappeared. C and C++ default initialize locals to garbage, not zero.
C++: ```cpp float x{}; // x == 0.0f float y = {}; // y == 0.0f struct Foo { float value{}; // automatically initialized to 0.0f }; ```

 explicit initializations.
```csharp class Foo { float value; // automatically 0f float[] values = new float[100]; // all 0f } ```
Aug 19
next sibling parent reply user1234 <user1234 12.de> writes:
On Wednesday, 19 August 2026 at 07:42:00 UTC, Serg Gini wrote:
 On Wednesday, 19 August 2026 at 07:31:14 UTC, Walter Bright 
 wrote:
 On 8/17/2026 7:03 AM, Quirin Schroll wrote:
 Maybe the next D Edition could require initialization of 
 types that don’t initialize with a value equal to `0`. D’s 
 behavior with these is annoying, because leads to needless 
 debug sessions, and also surprising because no other language 

 default-initialize to `0`.
My reply to this seems to have disappeared. C and C++ default initialize locals to garbage, not zero.
C++: ```cpp float x{}; // x == 0.0f float y = {}; // y == 0.0f struct Foo { float value{}; // automatically initialized to 0.0f }; ```

 explicit initializations.
```csharp class Foo { float value; // automatically 0f float[] values = new float[100]; // all 0f } ```
I think that your answer is a bit out-of-topic. We started on "default init" (implicit value expected) but here you show something that's more about "explicit init". That eventually falls back on a talk of a D language friend, IIRC, the Salt Lake City edition.
Aug 19
parent user1234 <user1234 12.de> writes:
On Wednesday, 19 August 2026 at 09:33:21 UTC, user1234 wrote:
 On Wednesday, 19 August 2026 at 07:42:00 UTC, Serg Gini wrote:
 On Wednesday, 19 August 2026 at 07:31:14 UTC, Walter Bright 
 wrote:
 On 8/17/2026 7:03 AM, Quirin Schroll wrote:
[...]
 I think that your answer is a bit out-of-topic. We started on 
 "default init" (implicit value expected) but here you show 
 something that's more about "explicit init". That eventually 
 falls back on a talk of a D language friend, IIRC, the Salt 
 Lake City edition.
sorry about the little inacuraccy, I was refering to Scott Meyers which was invited in Berlin edition 2017.
Aug 19
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Wednesday, 19 August 2026 at 07:42:00 UTC, Serg Gini wrote:

 ```csharp
 class Foo
 {
     float value;       // automatically 0f
     float[] values = new float[100]; // all 0f
 }
 ```
D: ```d void main() { float[int] aa; aa[0]++; writeln(a[0]); // ??? } ``` -Steve
Aug 19
parent monkyyy <crazymonkyyy gmail.com> writes:
On Wednesday, 19 August 2026 at 20:58:56 UTC, Steven 
Schveighoffer wrote:
 D:
 ```d
 void main() {
     float[int] aa;
     aa[0]++;
     writeln(a[0]); // ???
 }
 ```

 -Steve
1 :)
Aug 19
prev sibling parent Mike Shah <mshah.475 gmail.com> writes:
On Friday, 14 August 2026 at 06:38:02 UTC, Walter Bright wrote:
 Floats are default initialized to NaN so people will be coerced 
 to explicitly code what they want the initialized value to be.

 I've seen enough code where the programmer forgot to initialize 
 a float, it was defaulted to 0, and the wrong result was not 
 detected.

 ```d
 float f;     // code reviewer: did the programmer intend it to 
 be 0?
 float g = 0; // code reviewer: yes, the programmer likely meant 
 to initialize it to 0
 ```

 It's similar to pointers being default initialized to null. 
 Trying to use a null pointer will result in a seg fault.

 Most people decry this, but it's actually a great feature. If 
 there's a bug in the code, it's better to find it sooner rather 
 than after you ship.
It's helped me more than a handful of times when building a linear algebra math library to always explicitly initialize floating point values and never assume zero. I like NaN because the error propogates, it's very easy to detect and then debug NaN versus a garbage value which can sneak by. floating point numbers being initialized to NaN is a good reminder that while they're 'grouped' and often taught as 'a primitive type' -- they behave differently (i.e. drift error, can't represent everything, need to be compared carefully, etc.)!
Aug 17
prev sibling next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 14/08/2026 5:57 PM, ABrightLight wrote:
 Hello. I understand this subject's been discussed a number of times 
 before, but I'd like to throw in my reasoning for why it would benefit 
 us more for floats to initialize to 0 than NaN.
 
 1. float is generally used for numeric computation (things like NaN 
 boxing are examples of uses outside of this) and as such have similarity 
 to the integer types (they will even implicitly coerce mathematical 
 operations to float). Since integers default to 0, floats should too.
 
 1a. It may be argued that integers only default to 0 because there is no 
 meaningful "null" value, but in my opinion this is not convincing 
 because I think that most people would opt for them getting a reasonable 
 default value right from the start instead of being forced to `= 0;` It 
 is very common to see loop variables and other forms just say `int i;` 
 or similar, and no one is confused by this.
 
 2. It is argued that since, like pointers that have `null` and are 
 default initialized to this, floats should also initialize to its 
 version of `null`. However this is a false equivalence since the use of 
 a null pointer is specified/standardized to crash the program due to a 
 concern for memory safety (it's not even set to undefined behavior, a 
 program halt must occur). The same memory safety concern is not present 
 for most operations relying on floats, and the existence of NaN being 
 left without a crash [or even an exception thrown] is to cater to 
 performance. For cases where debugging by program halt is required, most 
 of the time the approach done is for a compiler switch to allow throwing 
 an exception instead of just halting the program, since a stack trace is 
 presumed to be desired.
I mentioned this else where, the reason it doesn't cause a hardware exception was a decision that D made, as it had bad interactions. The CPU can do it.
 3. I know that rikki's DFA implementation will be able to detect when a 
 `float x;` occurs without then being actually initialized to something 
 useful (keep up the great work rikki!), but this particular feature is a 
 special case that is not exactly within scope. And the fact that this is 
 even being added as a special case should be a hint that leaving NaN as 
 the default init is much less useful than some integer-compatible value 
 like 0.
Thanks. It is based upon preventing uninitialized variable reads. The main difference is it has been special cased so only a mathematical operation will trigger it. Other reads like returning it, won't. This is to prevent false positives, but could be changed if so desired.
Aug 14
parent Walter Bright <newshound2 digitalmars.com> writes:
Another problem with NaN signalling an exception is no longer having a value to 
be used for a bad pixel in your satellite's camera.
Aug 14
prev sibling next sibling parent reply Kapendev <alexandroskapretsos gmail.com> writes:
On Friday, 14 August 2026 at 05:57:55 UTC, ABrightLight wrote:
 Hello. I understand this subject's been discussed a number of 
 times before, but I'd like to throw in my reasoning for why it 
 would benefit us more for floats to initialize to 0 than NaN.
I'm in the `float.init = 0` team only because I know most people prefer the default to be `float.init = 0`. Arguments like "defining errors out of existence" or that NaN silently propagates are missing the point of NaN or what the main issue here really is. What is the main issue? It's who is going to write five extra characters. ```d float a = 0.0f; // Zero fans :( float a = float.nan // NaN fans :( ``` I never care about the default float value because I usually write: ```d auto number = 0.0f ``` No issue. I defined the error out of existence! Feels good to say that line. Only issue remaining are structs and generic code. Those two I get that it might be annoying to set default values only for floats.
Aug 14
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 9:23 AM, Kapendev wrote:
 Only issue remaining are structs and generic code.
 Those two I get that it might be annoying to set default values only for
floats.
You can set a default value for struct fields like this: ```d struct S { int a = 7; } S s; assert(s.a == 7); ``` Perfectamundo!
Aug 14
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Friday, 14 August 2026 at 05:57:55 UTC, ABrightLight wrote:
 Hello. I understand this subject's been discussed a number of 
 times before, but I'd like to throw in my reasoning for why it 
 would benefit us more for floats to initialize to 0 than NaN.
In all the years I have used D, whenever I have forgotten to initialize a floating point number, the fix was ALWAYS to initialize explicitly to 0, because that's what I expected and desired to happen. This is a big stain on D, and it disrupts everyone's work unnecessarily. The problem is the distance from the error to the result. I don't ever expect it to change. -Steve
Aug 14
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Ada was developed to be a safe language before NaNs existed. Being curious, I 
googled what Ada did with default initialization:

"Ada does not automatically default initialize standalone floating-point 
variables (or other scalar types) to a specific value like 0.0. If you declare
a 
floating-point variable without an explicit initialization expression, its
value 
is uninitialized, and reading it before assigning a value is erroneous
behavior."

and:

"Compilers like GNAT provide pragmas (such as Initialize_Scalars) or specific 
command-line flags during development to fill uninitialized scalar variables 
with invalid or abnormal values. This helps catch uninitialized variable bugs 
early via constraint checks rather than relying on an accidental default zero."

and:

"While standard Fortran does not enforce this by default, many legacy and
modern 
Fortran compilers (such as gfortran) include specific compiler options like 
-finit-real=nan. This instructs the compiler to initialize all unallocated or 
undefined real variables to a Signaling NaN (sNaN)."

Looks like I'm not the only one advocating this for bug reduction.



Some outside opinions:

https://stackoverflow.com/questions/1036686/is-it-a-good-idea-to-use-ieee754-floating-point-nan-for-values-which-are-not-set
Aug 14
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Saturday, 15 August 2026 at 04:42:24 UTC, Walter Bright wrote:
 Some outside opinions:

 https://stackoverflow.com/questions/1036686/is-it-a-good-idea-to-use-ieee754-floating-point-nan-for-values-which-are-not-set
We dont care about outsider theory, our **repeated** *personal* **experience** is that nan passed to a graphics api is a no op and its one of the slowest thing to debug. adr ran into it on camera, steve-l guy teachs kids raylib and sees the repeat again and again, etc etc etc etc C dev's reading a spec and dreaming has less evidential weight then a new programmer running into this once.
Aug 15
next sibling parent Kapendev <alexandroskapretsos gmail.com> writes:
On Saturday, 15 August 2026 at 13:28:42 UTC, monkyyy wrote:
 On Saturday, 15 August 2026 at 04:42:24 UTC, Walter Bright 
 wrote:
 Some outside opinions:

 https://stackoverflow.com/questions/1036686/is-it-a-good-idea-to-use-ieee754-floating-point-nan-for-values-which-are-not-set
We dont care about outsider theory, our **repeated** *personal* **experience** is that nan passed to a graphics api is a no op and its one of the slowest thing to debug. adr ran into it on camera, steve-l guy teachs kids raylib and sees the repeat again and again, etc etc etc etc C dev's reading a spec and dreaming has less evidential weight then a new programmer running into this once.
I agree with this guy 👆🙏
Aug 15
prev sibling next sibling parent Mindy Batek (0xEAB) <desisma heidel.beer> writes:
On Saturday, 15 August 2026 at 13:28:42 UTC, monkyyy wrote:
 a new programmer running into this once.
Let them who has run into this only once cast the first stone.
Aug 15
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/15/2026 6:28 AM, monkyyy wrote:
 On Saturday, 15 August 2026 at 04:42:24 UTC, Walter Bright wrote:
 Some outside opinions:

 https://stackoverflow.com/questions/1036686/is-it-a-good-idea-to-use-ieee754-floating-point-nan-for-values-which-are-not-set
We dont care about outsider theory, our **repeated** *personal* **experience** is that nan passed to a graphics api is a no op and its one of the slowest thing to debug. adr ran into it on camera, steve-l guy teachs kids raylib and sees the repeat again and again, etc etc etc etc
Sorry you had a bad initial experience with this. Default initialization is not the only way a NaN can be appear in floating point: https://en.wikipedia.org/wiki/NaN#Operations_generating_NaN There's no getting away from dealing with NaNs. Default initialization to zero is not going to make that go away. The std.math functions are all carefully crafted to correctly deal with NaNs. As for the graphics case, what happened is the error showed itself immediately, which is much better than having a subtle unintended 0 initialization that may go undetected for years. BTW, I like it when checking in a piece of code, and then the test suite promptly fails. To find the problem, I use a binary search on the PR to find out where the source is. This can be automated by using Dustmite: https://blog.dlang.org/archive/2020/04/13/dustmite-the-general-purpose-data-reduction-tool/
 C dev's reading a spec and dreaming has less evidential weight then a new 
 programmer running into this once.
New programmers need to learn about NaN anyway. There's no reason to believe that a 0.0 is always correct, and debugging it will be a lot harder.
Aug 15
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Saturday, 15 August 2026 at 22:48:11 UTC, Walter Bright wrote:
 As for the graphics case, what happened is the error showed 
 itself immediately, which is much better than having a subtle 
 unintended 0 initialization that may go undetected for years.
The intended initialization is 0 the vast majority of the time
 There's no getting away from dealing with NaNs. Default 
 initialization to zero is not going to make that go away. The 
 std.math functions are all carefully crafted to correctly deal 
 with NaNs.
false 0's are not unnoticeable they render at the origin or as pure black and I generally need to rewrite all math functions to *not* be nan friendly because nan propagating is a problem. Your just asserting terrible takes for video games, cause they aint airplane surgery. Failures that do something are amusing; doing nothing is very bad and all the c libs treat nan as a rareish value cause in c their data structures 0 initialize. There more a video game community then dlang airplane surgery companies.
Aug 15
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/15/2026 7:16 PM, monkyyy wrote:
 The intended initialization is 0 the vast majority of the time
Yes, you are correct.
 their data structures 0 initialize.
Use this for data structures: ```d struct S { float f = 0; // initializes struct to 0 } float[100] a = 0; // initializes array to 0 ``` Use calloc() to allocate memory for data structures.
Aug 19
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Thursday, 20 August 2026 at 04:02:47 UTC, Walter Bright wrote:
 ```d
 struct S {
     float f = 0;  // initializes struct to 0
 }
 float[100] a = 0; // initializes array to 0
 ```
I dont use a linter, your asking me to remember to do that every single time; I dont. Using your own agrument for auto initialization for everything else, this violates that. Your anti-initializing floats.
Aug 20
parent Kapendev <alexandroskapretsos gmail.com> writes:
On Thursday, 20 August 2026 at 12:46:30 UTC, monkyyy wrote:
 On Thursday, 20 August 2026 at 04:02:47 UTC, Walter Bright 
 wrote:
 ```d
 struct S {
     float f = 0;  // initializes struct to 0
 }
 float[100] a = 0; // initializes array to 0
 ```
I dont use a linter, your asking me to remember to do that every single time; I dont. Using your own agrument for auto initialization for everything else, this violates that. Your anti-initializing floats.
Happy ending. ![image](https://gcdnb.pbrd.co/images/r-SeOerZqhO7.png)
Aug 20
prev sibling parent Kapendev <alexandroskapretsos gmail.com> writes:
On Sunday, 16 August 2026 at 02:16:22 UTC, monkyyy wrote:
 Your just asserting terrible takes for video games
As a junior PHP web dev, I support NaN and don't support video games.
Aug 20
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/14/2026 2:25 PM, Steven Schveighoffer wrote:
 In all the years I have used D, whenever I have forgotten to initialize a 
 floating point number, the fix was ALWAYS to initialize explicitly to 0,
because 
 that's what I expected and desired to happen.
Yes, initializing to 0.0 is very common. And that works fine until the correct initialization is 0.001, and there's an unrecognized bug in the output.
 This is a big stain on D, and it disrupts everyone's work unnecessarily. The 
 problem is the distance from the error to the result.
The problem with default initialization to 0.0 is not recognizing that the result is in error, which I submit is much much worse. It costs orders of magnitude less money to fix a bug made very visible with a NaN output than output that is just slightly wrong and unnoticed out in the field. When reviewing code, and you see: ```d float f; ``` is the intention to initialize it to zero, or did the programmer simply forget to initialize it? I've had more than enough of the latter in actual code. P.S. In case it isn't obvious, this derives from my experience designing flight controls for the 757. You really really really want to find all the bugs before cutting metal or, heaven forbid, trying to lift it off the runway. Inconvenience be damned.
Aug 14
next sibling parent reply pete <email email.com> writes:
I guess it depends upon the use case. In my experience with 
mostly developing 3D apps and game code etc I have only ever 
wanted the default to be 0. I have had bad experiences with the 
nan default. One time it caused a massive slow down which delayed 
me for ages trying to understand what was causing the problem. I 
just assumed for a while that D was just slow. Other times it 
caused weird visual artifacts or incorrect rendering for no 
obvious reason.

 When reviewing code, and you see:
 ```d
 float f;
 ```
For what I do the above example is not the common problem. This is usually pretty easy to see either as a local or a global. My problem is when using a struct with a float I would generally assume that the float would be initialised to 0 (this is what C/C++ does for example and copying code examples from the web will have some C code such as: ``` typedef struct VkClearDepthStencilValue { float depth; uint32_t stencil; } VkClearDepthStencilValue; VkClearDepthStencilValue depthStencilClear = { .stencil = 0 }; or VkClearDepthStencilValue depthStencilClear = {0}; ``` I would assume the D equivalent would produce the same result because of course everything would just be zeroed by default :) ``` VkClearDepthStencilValue depthStencilClear; ``` No this produces a bug that is unexpected and may not be trivial to track down. I do understand the reasoning for defaulting to nan though. It is just that I have always wanted and expected it to be 0. I do love using D btw but this is one of the small quirks that usually I remember to work around :)
Aug 15
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/15/2026 3:13 AM, pete wrote:
 typedef struct VkClearDepthStencilValue {
      float       depth = 0;
      uint32_t    stencil;
 } VkClearDepthStencilValue;
will default initialize .depth to 0.0. May I suggest doing a grep across your C++ derived declarations looking for floats and doubles. BTW, C and C++ will default initialize all variables to garbage when they are declared as a function local! Those are very hard to track down. I once spent 3 days trying to track one down. It scarred me for life.
Aug 15
next sibling parent reply pete <email email.com> writes:
On Sunday, 16 August 2026 at 02:00:29 UTC, Walter Bright wrote:
 On 8/15/2026 3:13 AM, pete wrote:
 typedef struct VkClearDepthStencilValue {
      float       depth = 0;
      uint32_t    stencil;
 } VkClearDepthStencilValue;
will default initialize .depth to 0.0. May I suggest doing a grep across your C++ derived declarations looking for floats and doubles.
I usually do this now but I occasionally forget and it would not be obvious to someone who hadn't already been bitten by the problem in the first place. Most people would assume the default would just be zero and if you are going to violate the principle of least surprise by making it different then the result of using the nan should be immediate and obvious. If it worked like a null pointer dereference then it would make sense because they are easy to track down. The default nan is just the compiler working behind your back inserting poison. Then when you run it things just "don't work right" in non obvious ways and you either (1) leave it thinking you're just having a bad day at the keyboard or (2) debug the whole thing to see where the data deviates from what you expected and (2a) curse loudly when you realise what the compiler just did to you :)
Aug 16
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/16/2026 1:32 AM, pete wrote:
 Most people would assume the default would just be zero and if you are going
to 
 violate the principle of least surprise by making it different then the result 
 of using the nan should be immediate and obvious.
If 0.0 is the wrong initialization, then it is worse trying to detect the error. For example, 0.001 + 0.0 => 0.001 => overlooked error 0.001 + NaN => NaN => obvious error
Aug 18
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 18 August 2026 at 19:16:36 UTC, Walter Bright wrote:
 
 0.001 + 0.0 => 0.001 => overlooked error
The point of floats is to be pretend analog signals, handling small errors is fundamental to the type theory, your using floats because you have a continuous fuzzy decision. You take several of small decisions like a solar system of gravity vectors and sum them. Nan breaks this workflow because ops, everything is now nan.
Aug 18
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/18/2026 12:47 PM, monkyyy wrote:
 The point of floats is to be pretend analog signals, handling small errors is 
 fundamental to the type theory, your using floats because you have a
continuous 
 fuzzy decision.
 
 You take several of small decisions like a solar system of gravity vectors and 
 sum them. Nan breaks this workflow because ops, everything is now nan.
The purpose of NaN is to expose errors, not hide them.
Aug 18
prev sibling parent reply Serg Gini <kornburn yandex.ru> writes:
On Sunday, 16 August 2026 at 02:00:29 UTC, Walter Bright wrote:
 BTW, C and C++ will default initialize all variables to garbage 
 when they are declared as a function local! Those are very hard 
 to track down. I once spent 3 days trying to track one down. It 
 scarred me for life.
I think we should stop comparing with 50 years old languages. The bar is too low. I've checked what modern system languages are doing: Mojo, Swift, Zig and Rust are not allowing to declare uninitialized float. Go is making it 0.0
Aug 17
parent Juraj <junk vec4.xyz> writes:
On Monday, 17 August 2026 at 07:52:21 UTC, Serg Gini wrote:
 On Sunday, 16 August 2026 at 02:00:29 UTC, Walter Bright wrote:
 BTW, C and C++ will default initialize all variables to 
 garbage when they are declared as a function local! Those are 
 very hard to track down. I once spent 3 days trying to track 
 one down. It scarred me for life.
I think we should stop comparing with 50 years old languages. The bar is too low. I've checked what modern system languages are doing: Mojo, Swift, Zig and Rust are not allowing to declare uninitialized float. Go is making it 0.0
The main issue is `float.init`. Once you disallow implicit initialization, you need a way to express explicit initialization in templates. Any non trivial template will end up with something like `T tmp = T.init;` And if T is float, you are at square one, you get a silent NaN. Dlang shines when it takes proven things and makes them ergonomic (templates), when it tackle a problem and make it braindead trivial (metaprograming). But once it tries to "be different", even for the sake of correctness, it often fails. Juraj
Aug 17
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/15/2026 3:13 AM, pete wrote:
 (this is what C/C++ does for example and copying code examples from the web 
 will have some C code such as:
 
 ```
 typedef struct VkClearDepthStencilValue {
      float       depth;
      uint32_t    stencil;
 } VkClearDepthStencilValue;
 
 VkClearDepthStencilValue depthStencilClear = {
      .stencil = 0
 };
If you leave it as a C file, and then import it using Import C, the default initializer for `.depth` with be 0.0. (!!)
Aug 15
parent reply libxmoc <libxmoc gmail.com> writes:
On Sunday, 16 August 2026 at 02:33:42 UTC, Walter Bright wrote:
 On 8/15/2026 3:13 AM, pete wrote:
 (this is what C/C++ does for example and copying code examples 
 from the web will have some C code such as:
 
 ```
 typedef struct VkClearDepthStencilValue {
      float       depth;
      uint32_t    stencil;
 } VkClearDepthStencilValue;
 
 VkClearDepthStencilValue depthStencilClear = {
      .stencil = 0
 };
If you leave it as a C file, and then import it using Import C, the default initializer for `.depth` with be 0.0. (!!)
Would scoping 0 initialization to extern(C) struct (or under -betterC) make sense as a compromise?
Aug 16
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/16/2026 1:30 AM, libxmoc wrote:
 Would scoping 0 initialization to extern(C) struct (or under -betterC) make 
 sense as a compromise?
It would break the language into two incompatible dialects. extern(C) is not for semantic differences, it is just to match C calling conventions.
Aug 16
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 17/08/2026 3:48 PM, Walter Bright wrote:
 On 8/16/2026 1:30 AM, libxmoc wrote:
 Would scoping 0 initialization to extern(C) struct (or under -betterC) 
 make sense as a compromise?
It would break the language into two incompatible dialects. extern(C) is not for semantic differences, it is just to match C calling conventions.
Except that isn't quite true ;) ```d struct S {} static assert(S.sizeof <= 1); ```
Aug 16
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/16/2026 8:52 PM, Richard (Rikki) Andrew Cattermole wrote:
 Except that isn't quite true ;)
 
 ```d
 struct S {}
 static assert(S.sizeof <= 1);
 ```
It's a good point, but it still affects calling conventions because it affects the size of a struct.
Aug 16
parent reply pete <email email.com> writes:
There is something I don't understand here. If an uninitialised 
float is an error then why does the compiler not just raise it at 
compile time rather than setting it to a value that is always 
wrong and letting someone *hopefully* find it at runtime?

Even a signalling nan seems like the wrong choice from the start. 
If the compiler already knows where the problem is because it is 
the one that adds the nan then just stop compiling right there 
and let the programmer set it to whatever value they think is 
sensible.

I would be ok with a compiler flag that meant any uninitialised 
floats were treated as compiler errors so that I could fix them 
as soon as possible and not end up with a program that just 
doesn't work as intended.

A compiler that silently produces a binary with bugs in it is 
surely worse isn't it?
Aug 17
next sibling parent reply Guillaume Piolat <first.name gmail.com> writes:
On Monday, 17 August 2026 at 07:47:09 UTC, pete wrote:
 There is something I don't understand here. If an uninitialised 
 float is an error then why does the compiler not just raise it 
 at compile time rather than setting it to a value that is 
 always wrong and letting someone *hopefully* find it at runtime?
Change NaN with null and you'll see how that argument doesn't stand. Why would the compiler compile a pointer initialized to null?
Aug 17
next sibling parent pete <email email.com> writes:
On Monday, 17 August 2026 at 10:14:25 UTC, Guillaume Piolat wrote:
 On Monday, 17 August 2026 at 07:47:09 UTC, pete wrote:
 There is something I don't understand here. If an 
 uninitialised float is an error then why does the compiler not 
 just raise it at compile time rather than setting it to a 
 value that is always wrong and letting someone *hopefully* 
 find it at runtime?
Change NaN with null and you'll see how that argument doesn't stand. Why would the compiler compile a pointer initialized to null?
I do agree partially with this argument but at least a null will fail hard. Some people may also like the idea of compiler errors for uninitialised pointers. If you want it to start null you can set it explicitly. I am not advocating for this but it doesn't seem outrageous to me. I am in the initialise floats to 0 camp anyway so I am only suggesting this as a compromise solution.
Aug 17
prev sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 17/08/2026 10:14 PM, Guillaume Piolat wrote:
 On Monday, 17 August 2026 at 07:47:09 UTC, pete wrote:
 There is something I don't understand here. If an uninitialised float 
 is an error then why does the compiler not just raise it at compile 
 time rather than setting it to a value that is always wrong and 
 letting someone *hopefully* find it at runtime?
Change NaN with null and you'll see how that argument doesn't stand. Why would the compiler compile a pointer initialized to null?
But it does stand. ```d int* ptr; int val = *ptr; ``` Why should this clearly bad code compile? It shouldn't, and won't with clang or gcc if you turn on warnings. It also won't if you turn on the fast dfa engine. Nullability was first thing to get checked. Default! init floats were like second (it may not be in the next release but it is in ~master). It also has gained a borrow checker to protect reference counting types but Walter is not being helpful in getting it merged.
Aug 17
prev sibling next sibling parent user1234 <user1234 12.de> writes:
On Monday, 17 August 2026 at 07:47:09 UTC, pete wrote:
 There is something I don't understand here. If an uninitialised 
 float is an error then why does the compiler not just raise it 
 at compile time rather than setting it to a value that is 
 always wrong and letting someone *hopefully* find it at runtime?
 [...]
My understanding is that this would require complex static analysis which is somewhat possible (DFA) put not entirely due to call to extern C functions, or even D functions but linked using a separate compilation mode: ```d extern(C) void v(ref float); void f() { float f; // so init with NaN v(f); // what `v` will do on `f` is not known } ``` That being said, I'm on the zero-init camp too.
Aug 17
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/17/2026 12:47 AM, pete wrote:
 There is something I don't understand here. If an uninitialised float is an 
 error then why does the compiler not just raise it at compile time rather than 
 setting it to a value that is always wrong and letting someone *hopefully*
find 
 it at runtime?
Because of code like this: ```d float f; if (...) f = 1; else f = 2; ``` If the compiler gave an error for no initializer, the code will look like: ```d float f = 0; // shut up vacuous diagnostic message if (...) f = 1; else f = 2; ``` which is inelegant. Real cases of this tend to be more complex, which leaves the code reviewer with the task of determining why f is explicitly set to 0 when 0 is not the right value for f.
Aug 17
next sibling parent reply pete <email email.com> writes:
On Tuesday, 18 August 2026 at 03:25:37 UTC, Walter Bright wrote:
 On 8/17/2026 12:47 AM, pete wrote:
 There is something I don't understand here. If an 
 uninitialised float is an error then why does the compiler not 
 just raise it at compile time rather than setting it to a 
 value that is always wrong and letting someone *hopefully* 
 find it at runtime?
Because of code like this: ```d float f; if (...) f = 1; else f = 2; ``` If the compiler gave an error for no initializer, the code will look like: ```d float f = 0; // shut up vacuous diagnostic message if (...) f = 1; else f = 2; ``` which is inelegant. Real cases of this tend to be more complex, which leaves the code reviewer with the task of determining why f is explicitly set to 0 when 0 is not the right value for f.
I agree this looks a bit inelegant in this example. For more complex code I wouldn't mind at all manually setting f to nan if the compiler could not determine whether all flow paths resulted in f being set. In this case I would expect a code reviewer to also have an issue with it and manually setting it to nan would highlight that there could be a problem. I wouldn't really mind the nan default as long as there was a way of opting out. I would rather the compiler not use poison values if it can just easily ask me how to fix it during the compilation phase. Some people like poison values. Maybe for them the debugging for nan is trivial and that is fine. For some applications it is a pain and the main problem is that sometimes it doesn't even show up until much later.
Aug 18
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Thank you for your thoughts on this. It would be even better if there was a 
value that would cause an error immediately upon use. We do have that for 
pointers! But we don't for floating point (signalling NaNs were discussed 
elsewhere), so we just have to do our best.

BTW, the reason ints default initialize to zero is there is no value we can use 
as an invalid integer value. Some have proposed int.min, but nothing stops 
int.min from being part of a calculation and the result is no longer int.min so 
it is likely far more trouble than it's worth.

Designing a programming language is full of compromises. We just have to do the 
best we can.

Unlike C, which uses chars as integer types, D has a distinct char type. And so 
we can use the "invalid char value", or 0xFF, as its default initializer.
Aug 18
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, Aug 18, 2026 at 12:24:16PM -0700, Walter Bright via Digitalmars-d wrote:
[...]
 Designing a programming language is full of compromises. We just have
 to do the best we can.
 
 Unlike C, which uses chars as integer types, D has a distinct char
 type. And so we can use the "invalid char value", or 0xFF, as its
 default initializer.
D might as well use integer types for char, because char, wchar, and dchar implicitly convert to non-character int types. This happens even during overload selection: func(int) is preferred over func(dchar) when selecting an overload that calls `func` with a wchar argument. :-( T -- Some crows were looking eagerly at a piece of food in the middle of a busy street and wondering if they should go for it. It's a tempted murder!
Aug 18
parent reply Nick Treleaven <nick geany.org> writes:
On Tuesday, 18 August 2026 at 19:44:49 UTC, H. S. Teoh wrote:
 D might as well use integer types for char, because char, 
 wchar, and dchar implicitly convert to non-character int types. 
  This happens even during overload selection: func(int) is 
 preferred over func(dchar) when selecting an overload that 
 calls `func` with a wchar argument.
No: ```d char f(int) => 'i'; char f(dchar) => 'd'; void main() { import std.stdio; wchar w; w.f.writeln; // Error } ``` ``` charover.d(8): Error: `charover.f` called with argument types `(wchar)` matches multiple overloads after implicit conversions: charover.d(1): `charover.f(int __param_0)` and: charover.d(2): `charover.f(dchar __param_0)` w.f.writeln; ^ ``` I think implicit conversion from integer to character types is a more serious problem than going the other direction: ```d int i = 80; writeln("" ~ i); // prints 'P' ```
Aug 19
parent Nick Treleaven <nick geany.org> writes:
On Wednesday, 19 August 2026 at 09:55:56 UTC, Nick Treleaven 
wrote:
 I think implicit conversion from integer to character types is 
 a more serious problem than going the other direction:
 ```d
     int i = 80;
     writeln("" ~ i); // prints 'P'
 ```
Sorry, that does error actually - string ~ byte does work: ```d byte b = 80; writeln("" ~ b); // prints 'P' int i = 80; string s; s ~= i; // allowed writeln(""d ~ i); // prints 'P' ```
Aug 19
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, August 18, 2026 1:44:49 PM Mountain Daylight Time H. S. Teoh via
Digitalmars-d wrote:
 On Tue, Aug 18, 2026 at 12:24:16PM -0700, Walter Bright via Digitalmars-d
wrote:
 [...]
 Designing a programming language is full of compromises. We just have
 to do the best we can.

 Unlike C, which uses chars as integer types, D has a distinct char
 type. And so we can use the "invalid char value", or 0xFF, as its
 default initializer.
D might as well use integer types for char, because char, wchar, and dchar implicitly convert to non-character int types. This happens even during overload selection: func(int) is preferred over func(dchar) when selecting an overload that calls `func` with a wchar argument. :-(
I think that we're still better off with having character types, because it makes the code clearer, it does help with overloading (even if there are still issues), and it helps with character and string literals. However, I completely agree that the character types should not have been treated as integer types at all (so explicit casts would be required to convert them to any integer types), just like I think that bool should never have been an integer type. We're probably stuck at this point though, and at least in the bool case, Walter would never agree to stop treating it as an integer type. The C way of dealing with boolean values is just too deeply ingrained in him at this point. - Jonathan M Davis
Aug 19
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Casting is a hammer that overrides the type system. Hence one can plausibly 
argue that every cast is a bug in the program, or at least shows the programmer 
didn't do a good job selecting types properly. In my own code, I try to select 
types to minimize a need for casting.

Implicit conversions, however, are a "soft" conversion rather than a hammer. C 
is a bit too loose with that, as such can do hidden truncations. D's design is 
better because of Value Range Propagation.

Before C, I programmed in Wirth's Pascal. It all looked good in the manual, but 
in practice it was a horrible language. There were no implicit conversions, 
everything had to be constantly cast back and forth. So the hammer is 
everywhere. I disliked it strongly, and I think that was a big mistake in 
Pascal's design.

I've also always disliked C's "char" type because it is how one gets a byte 
integer, having nothing to do with characters. D fixes that.

But integral promotions are still retained, because doing integer operations on 
char's is not that unusual (such as upper/lower case conversions).

All in all, D's semantic selections for integral types are better than anyone 
else's for type safety and convenience.
Aug 19
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Wednesday, 19 August 2026 at 19:57:57 UTC, Walter Bright wrote:
 All in all, D's semantic selections for integral types are 
 better than anyone else's for type safety and convenience.
```d foreach(dchar d; "Über") { writeln(d); } foreach(dchar d; "Über".byCodeUnit) { writeln(d); } ``` The first prints 4 code points, each of the characters listed. The second prints 5 code points, the first two are the *integer promotion* of the two utf8 code units that encode "Ü" to dchar, which is nonsense. The second should not compile. It should be an error to implicitly promote char to dchar. It's a nonsense conversion that is allowed implicitly. Promoting to int is fine. But dchar is not an int. If you think this example is rare, wait until we remove autodecoding. -Steve
Aug 19
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/19/2026 2:17 PM, Steven Schveighoffer wrote:
 ```d
 foreach(dchar d; "Über") {
     writeln(d);
 }
 
 foreach(dchar d; "Über".byCodeUnit) {
     writeln(d);
 }
 ```
 
 The first prints 4 code points, each of the characters listed.
 
 The second prints 5 code points, the first two are the *integer promotion* of 
 the two utf8 code units that encode "Ü" to dchar, which is nonsense.
It does what it says on the box - gives 5 code units. The correct code should be: ```d foreach(dchar d; "Über".byDchar) { writeln(d); } ``` byCodeUnit is a building block. The documentation for it says, in part: " Many characters are encoded with multiple code units. For example, the UTF-8 code units for `▒` are `0xC3 0xB8`. That means, an individual element of `byCodeUnit` often does not form a character on its own. Attempting to treat it as one while iterating over the resulting range will give nonsensical results."
 The second should not compile. It should be an error to implicitly promote
char 
 to dchar. It's a nonsense conversion that is allowed implicitly.
Didn't H. S. Teoh argue that char should implicitly convert to wchar?
 Promoting to int is fine. But dchar is not an int.
 
 If you think this example is rare, wait until we remove autodecoding.
Aug 19
next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Aug 19, 2026 at 05:37:53PM -0700, Walter Bright via Digitalmars-d wrote:
 On 8/19/2026 2:17 PM, Steven Schveighoffer wrote:
[...]
 The second should not compile. It should be an error to implicitly
 promote char to dchar. It's a nonsense conversion that is allowed
 implicitly.
Didn't H. S. Teoh argue that char should implicitly convert to wchar?
[...] I never argued such a thing. I was arguing *against* implicitly converting any char type to an integer type. Yes, it's convenient to be able to do char math without casts, but the kind of bugs that crop up with inadvertent implicit conversion of char types to int is much more costly than this minor convenience. T -- Programming is not just an act of telling a computer what to do: it is also an act of telling other programmers what you wished the computer to do. Both are important, and the latter deserves care. -- Andrew Morton
Aug 19
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On Thursday, 20 August 2026 at 00:37:53 UTC, Walter Bright wrote:
 On 8/19/2026 2:17 PM, Steven Schveighoffer wrote:
 ```d
 foreach(dchar d; "Über") {
     writeln(d);
 }
 
 foreach(dchar d; "Über".byCodeUnit) {
     writeln(d);
 }
 ```
 
 The first prints 4 code points, each of the characters listed.
 
 The second prints 5 code points, the first two are the 
 *integer promotion* of the two utf8 code units that encode "Ü" 
 to dchar, which is nonsense.
It does what it says on the box - gives 5 code units.
It does not. Given the first statement's behavior, you would expect `dchar` type to mean *re-encode*, as this is what it is doing (this is a special compiler-generated decoding feature). But any char element type other than char arrays int promotes. Subtle changes in meaning for the same syntax are bug factories. This is why I really like `~` being the concat operator instead of `+`. If integer promotion to dchar didn't work, then you would know immediately what the problem is. -Steve
Aug 20
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Aug 19, 2026 at 12:57:57PM -0700, Walter Bright via Digitalmars-d wrote:
[...]
 I've also always disliked C's "char" type because it is how one gets a
 byte integer, having nothing to do with characters. D fixes that.
 
 But integral promotions are still retained, because doing integer
 operations on char's is not that unusual (such as upper/lower case
 conversions).
And that is where things go wrong. Upper/lowercasing via arithmetic works only for simplistic languages like English. Other languages require much more sophisticated algorithms (yes, algorithms) to do it correctly. And if you're already doing that, having implicit casting or explicit is no longer a deciding factor. Rather, the incorrectness of having a char literal match an int function over a wchar function becomes a source of bugs.
 All in all, D's semantic selections for integral types are better than
 anyone else's for type safety and convenience.
Convenience? Better than Pascal? Hardly. As things stand, you have to sprinkle casts everywhere in your D code anyway, if you happen to work with narrow integers. Not much better than Pascal. T -- "I'm running Windows '98." "Yes." "My computer isn't working now." "Yes, you already said that." -- User-Friendly
Aug 19
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/19/2026 2:25 PM, H. S. Teoh wrote:
 And that is where things go wrong.  Upper/lowercasing via arithmetic
 works only for simplistic languages like English.  Other languages
 require much more sophisticated algorithms (yes, algorithms) to do it
 correctly.  And if you're already doing that, having implicit casting or
 explicit is no longer a deciding factor.
Since you don't like the casing example, consider string-to-decimal and decimal-to-string conversions. P.S. I suspect the "simplistic" English is the result of 1) the explosive use of the printing press and 2) morse code and 3) the RADIX50 character set. These were all powerful pressures to simplify the written characters.
 Rather, the incorrectness of having a char literal match an int function
 over a wchar function becomes a source of bugs.
Function overloading is way overused, and yes, you can get into trouble with integral promotions and not covering the cases properly.
 All in all, D's semantic selections for integral types are better than
 anyone else's for type safety and convenience.
Convenience? Better than Pascal? Hardly. As things stand, you have to sprinkle casts everywhere in your D code anyway, if you happen to work with narrow integers. Not much better than Pascal.
You may be using a modern Pascal. I was using an early Pascal that implemented Wirth's "Pascal User Manual and Report". I know that Borland's Turbo Pascal had to add in lots of extensions to make it even possible to write a program in Pascal. For example, the original Pascal had to be all in one file. But there was one gem in Pascal - nested functions. And D has them!
Aug 19
next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Aug 19, 2026 at 05:01:10PM -0700, Walter Bright via Digitalmars-d wrote:
 On 8/19/2026 2:25 PM, H. S. Teoh wrote:
[...]
 Convenience?  Better than Pascal?  Hardly.  As things stand, you
 have to sprinkle casts everywhere in your D code anyway, if you
 happen to work with narrow integers.  Not much better than Pascal.
You may be using a modern Pascal.
[...] I don't actually use any Pascal (I dislike it for pretty much the same reasons as yours). My point is that current D integer promotion rules make narrow ints a royal pain to work with. A pain on the level of working with casts in Pascal. For example: ```d ubyte x; x++; // OK x += 1; // OK x = x + 1; // NG (WAT?) x = cast(ubyte)(x + 1); // Pascal-level of annoyance ``` And this is just a trivial example. When you have a complex expression involving narrow ints, the level of annoyance quickly becomes unbearable. T -- If anyone wants a copy of Orthopedics Today, I have back issues.
Aug 19
prev sibling parent Luna <luna foxgirls.gay> writes:
On Thursday, 20 August 2026 at 00:01:10 UTC, Walter Bright wrote:
 On 8/19/2026 2:25 PM, H. S. Teoh wrote:
 And that is where things go wrong.  Upper/lowercasing via 
 arithmetic
 works only for simplistic languages like English.  Other 
 languages
 require much more sophisticated algorithms (yes, algorithms) 
 to do it
 correctly.  And if you're already doing that, having implicit 
 casting or
 explicit is no longer a deciding factor.
Since you don't like the casing example, consider string-to-decimal and decimal-to-string conversions. P.S. I suspect the "simplistic" English is the result of 1) the explosive use of the printing press and 2) morse code and 3) the RADIX50 character set. These were all powerful pressures to simplify the written characters.
Other countries with less simplistic type systems had their own printing press evolution and had to develop alternatives to things such as morse code. Hell Windows sucks at multilingual use due to the fact that it’s still stuck in pre-Unicode semantics under the hood where each country and language had their own text encoding. Which is why if you get a text document from Iceland it may be misinterpreted as Danish and lead to gibberish text, due to text frequency analysis that windows does being flawed. Japan still clings on to Shift-JIS text encoding in many places which is a fixed-width 16-bit encoding that is incompatible with ASCII and Unicode. Simply because it can represent some things better than the alternatives. So no, it’s more a side effect of US and UK inventors seeing themselves as the center of the world and leaving the rest of us to clean up the mess they made.
Aug 20
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, August 19, 2026 1:57:57 PM Mountain Daylight Time Walter Bright
via Digitalmars-d wrote:
 Casting is a hammer that overrides the type system. Hence one can plausibly
 argue that every cast is a bug in the program, or at least shows the programmer
 didn't do a good job selecting types properly. In my own code, I try to select
 types to minimize a need for casting.

 Implicit conversions, however, are a "soft" conversion rather than a hammer. C
 is a bit too loose with that, as such can do hidden truncations. D's design is
 better because of Value Range Propagation.

 Before C, I programmed in Wirth's Pascal. It all looked good in the manual, but
 in practice it was a horrible language. There were no implicit conversions,
 everything had to be constantly cast back and forth. So the hammer is
 everywhere. I disliked it strongly, and I think that was a big mistake in
 Pascal's design.

 I've also always disliked C's "char" type because it is how one gets a byte
 integer, having nothing to do with characters. D fixes that.

 But integral promotions are still retained, because doing integer operations on
 char's is not that unusual (such as upper/lower case conversions).

 All in all, D's semantic selections for integral types are better than anyone
 else's for type safety and convenience.
D has definitely done a better job with type conversions than any other language that I've used, but I also think that it would be better by being stricter with some of its conversions (particularly to integer types). IMHO, there are still too many corner cases where implicit conversions cause subtle issues. So, I do think that we're better off than the competition, but we could do better than we're currently doing. As for explicit casts being an issue, I think that part of the problem is that we only have the one cast operator which tries to do everything, including the really blunt casts that aren't safe. Having std.conv.to helps, because it has a more restricted set of conversions, but it's also overly generalized for many situations where there would ideally be fewer conversions available so that it's much less likely that refactoring would break the code in subtle ways. For instance, the fact that the same cast operator which is used to do a narrowing conversion is also used to do bit casting is a bit of a footgun. It's certainly manageable, but I feel that there are a number of situations where a cast is currently required or would ideally be required where you don't want to have to worry about accidentally reinterpreting the bits of what you're casting. Being able to do something like convert from a floating point type to an integer type with a conversion that's only allowed to work between floating point and integer types rather than trying to convert _any_ type to an integer type would be less error-prone, particularly when refactoring code. I'm not sure that I have a great solution to the problem, but I do think that there's a middle ground between allowing implicit conversions and using the cast operator. In some cases, it would probably be a good idea to provide functions to do specific types of conversions in a checked manner (e.g. only allowing a specific subset of conversions based on a template constraint), but I've also sometimes thought that it would be nice to have an explicit implicit cast (for lack of a better term) where there's only a specific set of conversions that are allowed (similar to what you get with an implicit conversion now), but it's explicit. Perhaps explicit construction would be one way to do that, or some other operator could be introduced. So, for instance, let's say you could do something like `int('A')` but `int i = 'A';` would be illegal, and a function that accepted int wouldn't accept char. That way, you wouldn't need to use `cast(int) foo` and risk accidentally doing a bit cast on some other type when the code was refactored, and the type of foo changed from something with a sensible conversion to int to something that did a bit cast in order to be converted to int. I'm not currently proposing that we make any such changes in D (and even if we wanted to, we'd have to be very careful about it because of all of the existing code which allows a variety of implicit conversions that we would ideally restrict), but there's no question that if I were to create my own language, I'd reduce the number of implicit conversions in comparison to what D has, and I'd provide ways to convert types which did not involve a cast operator which could do any sort of unsafe cast. IMHO, D's cast operator just does way too much and makes it far too easy to do one type of cast when you intended to do a different one - and/or to have the type of cast changee in unintended ways when code is refactored. - Jonathan M Davis
Aug 19
prev sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 18/08/2026 7:16 PM, pete wrote:
 I agree this looks a bit inelegant in this example. For more complex 
 code I wouldn't mind at all manually setting f to nan if the compiler 
 could not determine whether all flow paths resulted in f being set. In 
 this case I would expect a code reviewer to also have an issue with it 
 and manually setting it to nan would highlight that there could be a 
 problem.
 
 I wouldn't really mind the nan default as long as there was a way of 
 opting out. I would rather the compiler not use poison values if it can 
 just easily ask me how to fix it during the compilation phase. Some 
 people like poison values. Maybe for them the debugging for nan is 
 trivial and that is fine. For some applications it is a pain and the 
 main problem is that sometimes it doesn't even show up until much later.
I'm ok with this, however this is going to be a pretty invasive change and its stops being simply a static analysis feature of the compiler. Its a good example of why I'm not writing out the exact behavior of the fastdfa engine, I want people to interpret the results of their experience and judge when they think it should or shouldn't be activating, because it is dependent on the user base on how it should be configured. For these kinds of problems its a sociological problem to what extent people are willing put up with false positives.
Aug 18
prev sibling parent Forum User <forumuser example.com> writes:
On Tuesday, 18 August 2026 at 03:25:37 UTC, Walter Bright wrote:
 On 8/17/2026 12:47 AM, pete wrote:
 There is something I don't understand here. If an 
 uninitialised float is an error then why does the compiler not 
 just raise it at compile time rather than setting it to a 
 value that is always wrong and letting someone *hopefully* 
 find it at runtime?
Because of code like this: ```d float f; if (...) f = 1; else f = 2; ```
Regardless of how the value `f` is initialzed, this style has a problem: The initial value of `f` is discarded. I think that discarding values shall be avoided. Thus I write the initialization: ```d float f = (...) ? 1 : 2; ``` Compiler warnings/errors like "Defined but not used" are known for variables. Is there a similar facility for values?
Aug 19
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Saturday, 15 August 2026 at 06:11:23 UTC, Walter Bright wrote:
 On 8/14/2026 2:25 PM, Steven Schveighoffer wrote:
 In all the years I have used D, whenever I have forgotten to 
 initialize a floating point number, the fix was ALWAYS to 
 initialize explicitly to 0, because that's what I expected and 
 desired to happen.
Yes, initializing to 0.0 is very common. And that works fine until the correct initialization is 0.001, and there's an unrecognized bug in the output.
1. If this was the correct value, I would initialize it to 0.001. What if the correct value is 0.001 and you accidentally use 0.01? 2. If you forgot, the chances of 0 not showing up somewhere are slim. If it's supposed to be a factor, all of a sudden all your values are unexpectedly 0. If it's supposed to be an epsilon, then most likely your code fails to work correctly. If it's supposed to be an addition factor, then likely 0 is close enough that it's not important, or it makes a difference and you notice. 3. NaN isn't significantly more likely to be seen than erroneous 0. Most code that uses floats doesn't print them. NaN has weird properties. Maybe it's used in a comparison, and is always false. How is that obvious? Ever see NaN show up on a UI? How is that possible since NaN is so obvious to the developer they would have fixed it before release? 4. I would actually be *OK* with NaN as a default if it failed on first use. The problem with it is that it propagates far away from the actual error. Null is different, it fails immediately and loudly. 5. What about ints? Sometimes the default value of 0 is not right, and it should be 1. How do we cope with programming when ints default to 0? 0 is a better default, a consistent default, an expected default, and good default values make programming more pleasant.
 This is a big stain on D, and it disrupts everyone's work 
 unnecessarily. The problem is the distance from the error to 
 the result.
The problem with default initialization to 0.0 is not recognizing that the result is in error, which I submit is much much worse. It costs orders of magnitude less money to fix a bug made very visible with a NaN output than output that is just slightly wrong and unnoticed out in the field.
This is just hypothesizing. If 0 isn't the right value, then most likely you will see the error. Show some real world examples of NaN showing up when *erroneous* 0 would not have. In all my cases, NaN shows up because it *should have been* 0.
 When reviewing code, and you see:
 ```d
 float f;
 ```
 is the intention to initialize it to zero, or did the 
 programmer simply forget to initialize it? I've had more than 
 enough of the latter in actual code.
```d int i; ``` Same thing. In D, it is reasonable to expect a 0 init for a declared variable. I use it all the time. If you are used to C, yeah, the default (random data) is bad. Note that at least C has `= {0}` which allows you to zero everything in a struct regardless of nested data structure. D doesn't have this.
 P.S. In case it isn't obvious, this derives from my experience 
 designing flight controls for the 757. You really really really 
 want to find all the bugs before cutting metal or, heaven 
 forbid, trying to lift it off the runway. Inconvenience be 
 damned.
It's not obvious how this is relevant. NaN's are in actual released code, I've seen them. They do not magically expose all errors. What prevents errors is actual good tests. And you can always init to NaN explicitly if you want, just like today you can init to 0 if you want. 0 being correct is way way way more likely than NaN exposing a bug that an erroneous default 0 would not. This just makes for more busywork for the developer, for zero benefit. -Steve
Aug 16
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Thank you for the excellent summary of your question. I believe I have
responded 
to all these points at one point or another in this thread, so repeating it ad 
nauseam just will go nowhere.

Hence, with DConf coming up, I recommend we have a discussion on this over a 
beer! And, of course, anyone else can join us!
Aug 16
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 17/08/2026 3:58 PM, Walter Bright wrote:
 Thank you for the excellent summary of your question. I believe I have 
 responded to all these points at one point or another in this thread, so 
 repeating it ad nauseam just will go nowhere.
 
 Hence, with DConf coming up, I recommend we have a discussion on this 
 over a beer! And, of course, anyone else can join us!
Sounds like a lightning talk to me.
Aug 16
prev sibling next sibling parent Guillaume Piolat <first.name gmail.com> writes:
On Friday, 14 August 2026 at 05:57:55 UTC, ABrightLight wrote:
 Hello. I understand this subject's been discussed a number of 
 times before, but I'd like to throw in my reasoning for why it 
 would benefit us more for floats to initialize to 0 than NaN.
There is nothing to "fix" because NaN init is the right choice. I work in float all the time (audio) and this "issue" is not even an issue, when I happen to have a NaN bug I'm actually glad I can track it down so easily thanks to its stickyness. There are lot of things I'd want out of D floating point way before that: - A way to warn for downcasts from double to float like -vtls. Domain-specific use but very much relevant. - Making "fast math" options illegal, as they are enticing, vague and very dangerous. - `real` could disappear, again this has been debated for days with no point. It doesn't hurt eigher to be here... just line NaN init.
Aug 16
prev sibling next sibling parent Dukc <ajieskola gmail.com> writes:
On Friday, 14 August 2026 at 05:57:55 UTC, ABrightLight wrote:
 2. It is argued that since, like pointers that have `null` and 
 are default initialized to this, floats should also initialize 
 to its version of `null`. However this is a false equivalence 
 since the use of a null pointer is specified/standardized to 
 crash the program due to a concern for memory safety (it's not 
 even set to undefined behavior, a program halt must occur). The 
 same memory safety concern is not present for most operations 
 relying on floats, and the existence of NaN being left without 
 a crash [or even an exception thrown] is to cater to 
 performance.
I don't think so. Using NaN will result in another NaN, so eventually the error will show up, unless you end up discarding the value and not using it anyhow. Just as good as aborting immediately. Well, except for casts and comparison operators. IMO there should be an error if you try to compare a NaN to anything or cast it to an integer. Currently those cases are what lead to silent failures.
Aug 17
prev sibling parent GB <gb254 gmail.com> writes:
On Friday, 14 August 2026 at 05:57:55 UTC, ABrightLight wrote:
 Hello. I understand this subject's been discussed a number of 
 times before, but I'd like to throw in my reasoning for why it 
 would benefit us more for floats to initialize to 0 than NaN.

 1. float is generally used for numeric computation (things like 
 NaN boxing are examples of uses outside of this) and as such 
 have similarity to the integer types (they will even implicitly 
 coerce mathematical operations to float). Since integers 
 default to 0, floats should too.

 1a. It may be argued that integers only default to 0 because 
 there is no meaningful "null" value, but in my opinion this is 
 not convincing because I think that most people would opt for 
 them getting a reasonable default value right from the start 
 instead of being forced to `= 0;` It is very common to see loop 
 variables and other forms just say `int i;` or similar, and no 
 one is confused by this.

 2. It is argued that since, like pointers that have `null` and 
 are default initialized to this, floats should also initialize 
 to its version of `null`. However this is a false equivalence 
 since the use of a null pointer is specified/standardized to 
 crash the program due to a concern for memory safety (it's not 
 even set to undefined behavior, a program halt must occur). The 
 same memory safety concern is not present for most operations 
 relying on floats, and the existence of NaN being left without 
 a crash [or even an exception thrown] is to cater to 
 performance. For cases where debugging by program halt is 
 required, most of the time the approach done is for a compiler 
 switch to allow throwing an exception instead of just halting 
 the program, since a stack trace is presumed to be desired.

 3. I know that rikki's DFA implementation will be able to 
 detect when a `float x;` occurs without then being actually 
 initialized to something useful (keep up the great work 
 rikki!), but this particular feature is a special case that is 
 not exactly within scope. And the fact that this is even being 
 added as a special case should be a hint that leaving NaN as 
 the default init is much less useful than some 
 integer-compatible value like 0.

 P.S. This subject is a bit subjective (no pun intended) but 
 overall we'd likely see more user satisfaction from the float 
 init switch. And from what I could tell, it's been well 
 received by the OpenD folks, so there's already been a bit of a 
 testbed for this.
The debate is treating a symptom-management mechanism as though it were an invariant-enforcement mechanism. float.init == 0 vs float.init == NaN is somewhat of a distraction. A sentinel value is not the same thing as an invariant. The default value can absolutely affect how bugs manifest, but you should not be relying on a language's default initialization to establish a semantic invariant. The default value is irrelevant to establishing that invariant. Better to rely on the relationship between a value and the meaning the next operation assumes it has. That's the more fundamental issue here: not whether the default value is 0 or NaN, but whether the value still means what the operation consuming it assumes it means. Interestingly, that is what this book, 'The Wrong Memory', is all about. The dangerous bug isn't necessarily the wrong value, but the moment when a value stops meaning what we think it means. https://strawberry9.github.io/the-wrong-memory/cover.html
Aug 20