3 ms·
To be exact, all of these languages are statically typed and were created or at least started taking their final shape[1] after 2009, when Tony Hoare (who has t
by unscaled 2y ago
To be exact, all of these languages are statically typed and were created or at least started taking their final shape[1] after 2009, when Tony Hoare (who has the best claim for being the one who invented the null reference) coined the term "Billion Dollar Mistake" and made the final convincing argument as to why no serious typed language should have null.
But it's probably more important than all of these languages have been heavily influenced by the ML/Haskell family of languages. Most ML-influenced languages forbid null references, discourage them or make nullability a part of the type signature. I think the ML-heritage is the key factor, together with Tony Hoare's influence.
Languages released shortly after 2009 that have ignored the ML tradition like Go and Dart did not have null-safety. I believe ML-influenced language designers were more attuned to Tony Hoare's call for action and had a good idea about how to make null-safety work smoothly an industrial language.
Fortunately for us, nowadays the language designer doesn't have to be a Functional Programming aficionado anymore: null-safety has proven itself as relatively easy to implement and too useful to ignore.
---
[1] Rust is the odd one out here: Graydon has started working on Rust as a personal project back in 2006, but that language is bears little resemblence to what we call Rust today. Rust only became more than a personal project around 2009 and the first release (0.1) only came in 2012. Looking around, I find no reference for avoiding null reference in Rust before 2010.
- tadfisher 2y ago> [...] made the final convincing argument as to why no serious typed language should have null. Null is a perfectly valid and very useful feature, if modeled in the type system. A nullable reference of type, say, "T?", would accept values accepted by T or the special value "null", which is equivalent to a union type of "T | Void" (or whatever type is assigned to "null" in your language). The billion-dollar-mistake is not the existence of null references, but the inability to model nullability in the type system, thus making references implicitly nullable. You can ban the concept of null from your language, but you're inevitably going to add lots of syntax sugar or helper functions to unwrap "Optional<T>" or "Maybe t" values, so making nullability a "type modifier" has equivalent behavior and, IMO, better ergonomics.
- Nullabillity 2y ago> Null is a perfectly valid and very useful feature, if modeled in the type system. No it isn't, because union types leak through generics in surprising ways. For example: // value is null if not loaded yet struct AsyncSnapshot<T> { value: T? } // returns null if user is not found fn getUser(id: Id<User>): User? fn runInBackground<T>(f: () -> T): Stream<AsyncSnapshot<T>> If you run `runInBackground({ getUser(id) })`, `AsyncSnapshot<T?>`'s `value` gets the type `T??` which is typically coalesced to `T?` and you can't tell whether it's `null` because there is no user, or because it's still loading. Sum types like `Option<T>` do not coalesce, `Option<Option<T>>` is distinct from `Option<T>`. Better yet, you can declare your own clearer sum types, so you can have `MaybeLoaded<MaybeExists<User>>` rather than have to remember which layer is which.
- tadfisher 2y agoThat doesn't make it not useful, but I agree with your conclusion.