I was reading the excellent book by Axel Raushmayer, Tackling TypeScript.
In this section of Chapter 7, the author makes the interesting claim
In many programming languages, null is part of all object types. For example, whenever the type of a variable is String in Java, we can set it to null and Java won’t complain.
I am a little confused by the claim of “many” here. Exactly how many languages do this? C++ doesn’t, as pointer types are explicit (a string
can never be null, but a string*
can have the value nullptr
). Neither does C. Neither do Rust, Swift, TypeScript, etc. Certainly all dynamically languages do not, as they have a Null or NoneType or similar. C# does because of its Java ancestry, and Go has nil
for its reference types.
The way I understand the programming language landscape, it was Java that introduced this version of the billion dollar mistake, though they may have stolen it from an early Algol. And I don’t believe it is common at all.
Am I correct that this claim is misleading at best and that it is only Java (and C# and Go?) among modern static programming languages that conflate nulls with object types? If the claim is correct, then there is much about language type systems I don't understand, and was hoping the community here could come up with a list of popular languages for which this situation holds.
(I'm asking on software engineering stack exchange rather than the computer science stack exchange since the problem of having null values in static object types has, we all know, many ramifications for engineering correct and secure code. Regarding what I have tried so far, I've looked at all the languages mentioned above, as well as Julia, the ML family of languages, and more.)
CLARIFICATION
In response to some comments, I think I need to be more clear about the question. The question is independent of value or reference semantics (copy vs. sharing), and independent of primitive or non primitive types, and independent of mutability vs. immutability.
The language Java automatically, implicitly, adds an extra member to many types. For example, when giving a variable a type constraint such as:
String supervisor;
we can assign the value null
to the variable supervisor
. Now I think it is reasonable to take the point of view that null
is not a string: it does not have a length, it can not be reversed, etc. In fact the very use of null
is to indicate there is no supervisor. So including null
in the type is clunky at best and confusing at worst (and yes, I know about NaN
). I totally get that it's here because it is "easy," and this is exactly what Tony Hoare admitted in his famous Billion Dollar Mistake mea culpa.
Now languages with optionals built-in from the ground up (Swift, Rust, Haskell) and those with explicit pointers (C, C++), would never, ever allow anything other than an actual string to be assigned to a variable constrained to type string. Yet Java does. I am asking whether anyone knows of any other languages that do. I do not suspect there are many, that's all. :)
string
, say, means it can only hold values of thestring
type. It is impossible to assignnullptr
to such a variable. For examplestring s = nullptr;
is a type error in C++ (you have to saystring* p = nullptr;
), whileString s = null;
is perfectly fine in Java. C++ does is right by makingstring
andstring*
completely different types. Java is weird IMHO by makingString
refer to the union of strings and the null value. Hope that clears it up!nil
which seems to work roughly the same way asnull
in Java. Can you explain what difference you see?String x
in C++ is ashared_ptr<string> x
(much more similar thanstring *x
orstring &x
, not astring x
). Andshared_ptr
variables can be null. C# also distingusihes between reference types and value types. reference types could be null in the past. but starting with C#10, even reference type variablesT x
cannot be null by default unless one allows them to be explicitly by declaring them asT? x
(this is a feature which can be switched off for backwards compatibility).