Hacker News new | ask | show | jobs
by davidatbu 1439 days ago
The Billion Dollar Mistake refers to the fact that things that are not explicitly marked as "nullable" can be null/nil.

In rust, you would annotate score as `Option<u32>` (`u32` is one of Rust's integer types), and then you would set the score of someone who hasn't sat the test yet as `None`, and someone who got a 100 on the test as `Some(100)`.

2 comments

Also, because Rust is intended for writing low level software where you might very well care deeply about how big this type is:

Rust has NonZero versions of the unsigned types, so NonZeroU32 is the same size as a u32, four bytes with an unsigned integer in it, except it is never zero.

Option<NonZeroU32> promises to be exactly the same size as u32 was. Rust calls the space left by the unused zero value a "niche" and that's the perfect size of niche for None.

As a result you get the same machine code you'd have for a "normal" 32-bit unsigned integer with zero used as a sentinel value, but because Rust knows None isn't an integer, when you mistakenly try to add None to sixteen in some code deep in the software having forgotten to check for the sentinel you get a compile error, not a mysterious bug report from a customer where somehow it got 16 which was supposed to be impossible.

When a maintenance programmer ten years later decides actually zero is a possible value for this parameter as well as "None", there's a NonZeroU32, they swap it for u32, and the program works just fine - but because there's no niche left in u32 the type is now bigger.

Oh yeah, allowing values to be nullable by default is bad, that's totally different than just 'including null'. I thought they meant including null in the language!

> you would set the score of someone who hasn't sat the test yet as `None`

Yep that's what I expected. Emoji thumbs up.

>Oh yeah, allowing values to be nullable by default is bad, that's totally different than just 'including null'.

In Rust (and Haskell and OCaml for that matter), there is no built-in null keyword. Option is just an enum in the library that happens to have a variant called None. So it's technically Option::None and Option::Some(x). But, really, it could be Quux and Quux::Bla and Quux::Boo(x) instead--without any language changes.

That is vastly better that what IntelliJ does for Java with their weird @NonNull annotations on references--which technically still can be the null. null is still a keyword there, and null is somehow a member of every reference type (but not of the other types--how arbitrary).

And C# has a null keyword, and the rules for type autoconverting it are complicated, and some things you just aren't allowed to do with null (even though they should be possible according to the rules) because then you'd see what mess they made there (you'd otherwise be able to figure out what the type of null is--and there's no "the" type there. null is basically still a member of every type. And that is bad).

So even the language used in "allowing values to be nullable by default" is insinuating a bad idea. Nullability is not necessarily a property that needs to exist on values in the first place (as far as the programming language is concerned).

For all practical purposes, in C# with nullability checks enabled, null is not a member of every type anymore: T? includes null, while T does not.