5 ms·
The problem isn't null itself, but that many languages use nullable types by default. Null is a damn useful construct and while there may be better solutions t
by meddlepal 10y ago
The problem isn't null itself, but that many languages use nullable types by default.
Null is a damn useful construct and while there may be better solutions to using a null reference they're often not as clear as using null or worth the time investment to develop properly.
So yea, I generally try to avoid null's and completely understand how they've caused a lot of problems, but I'm not willing to say we shouldn't have them or use them when appropriate.
- kazagistar 10y agoYou don't just not use nulls, you replace them with something like Optionals. With a bit of language support, they can compile down to nulls but provide a layer of type safety and convenience functions.
- kmiroslav 10y agoIt's perfectly fine to use nulls in languages that encode them in their type system, e.g. Kotlin.
- junke 10y agoExactly. The problem is not that there is a null, it is that it is a valid value for all types (e.g. you can pass null to a function that expects a String). Allowing nulls explicitly, like with a "String?" type, is the way to go in languages where Option is not an option.
- kqr 10y agoIsn't it, in practise, basically the same thing though? The theoretical difference is this: 1. Option is a regular data type/object that represents "a collection of at most one value". It's similar to a list, set, heap, tree or whatever other collection types you have, except it can not contain more than one value. 2. With explicit nulls I guess any data type (e.g. Integer) will automatically get a clone of itself (a different type named Integer?) where also null is a valid member. From a purely theoretical standpoint, I like #1 better.
- greydius 10y agoIn practice, it's not the same thing. Here's a Java example where I want the type system to enforce that a method in `ClassB` can only be called from `ClassA`. However, the fact that `null` circumvents the type system makes this pattern just wishful thinking. class ClassA { private static final Witness witness = new Witness(); final static class Witness { private Witness() {} } void callClassBMethod(ClassB classB) { classB.onlyClassACanCallThisMethod(witness); } } class ClassB { void onlyClassACanCallThisMethod(ClassA.Witness witness) { // ... } }
- kmiroslav 10y agoThe downside of `Option` is that it's a wrapper, and as such, you need to `flatMap` (or similar) whenever you want to access the wrapped value. By encoding `null` in its type system, Kotlin lets you manipulate these values directly which leads to code that is much less noisy and just as safe.
- airless_bar 10y agoNot really. The main strength of the first approach is that Option is only one type out of many error-handling structures. Not every error is handled appropriately by Option/?. If you have a language like Kotlin where they hard-coded one way of handling errors, it feels very unidiomatic to pick a better fitting error handling type, while in languages where errors are handled by library code, it's a very natural approach.
- kmiroslav 10y ago> Not every error is handled appropriately by Option/?. Which is expected since these two constructs are not aimed at handling errors: they manage missing values. > If you have a language like Kotlin where they hard-coded one way of handling errors No, no. `?` is not for handling errors. Kotlin is as agnostic as Scala for managing errors: you are free to use exceptions, dumb return values or smarter ones (`Either`, `\/`, `Try`, ...).
- pjmlp 10y agoEiffel was one of the very first ones to have that feature actually, around 2006 when the language was revised for the ECMA standard. https://www.eiffel.org/doc/eiffelstudio/Differences%20between%20standard%20ECMA-367%20and%20Eiffel%20Software%20implementation#Void-safety https://www.eiffel.org/doc/eiffelstudio/Differences%20betwee...
- legulere 10y agoThis is e.g. what rust does. Another advantage of this is that you can also use them with types that aren't pointers (e.g. chars, integers, enums).
- yxlx 10y agoI would like to read about this. Got any links?
- legulere 10y agoOption<T> is just a normal enum in Rust. Enums can also can have parameters in Rust. Those are usually called tagged union in non-rust-speak. It's either Some(x) or None. It has a pretty easy definition: https://doc.rust-lang.org/std/option/enum.Option.html https://doc.rust-lang.org/std/option/enum.Option.html Storing None for an Option<&T> as a null and Some(ref) just as the reference is an special optimisation that the rust compiler does. Usually you have a selector which tells you which variant of the enum it is.
- 0xfaded 10y agoTree *a = new Leaf(); Tree *b = new Leaf(); Tree *c = new Node(a, b); a.parent = b.parent = c; null has other uses, e.g. as above for cyclically dependent initialisation.
- kazagistar 10y agoFirst, to some extent, your code is more a demonstration of the weakness of imperative vs declarative code, since, for example, Haskell lets you declare recursive structures directly, since it doesn't enforce an order of execution where none is needed. data Tree = Leaf Tree | Node Tree Tree a = Leaf c b = Leaf c c = Node a b But more importantly, there is no reason you can't do this with Optionals. Tree *a = new Leaf(); Tree *b = new Leaf(); Tree *c = new Node(a, b); a.parent = b.parent = new Some(c);
- bogomipz 10y agoOn a related note and at the risk of sounding obtuse here - if you didn't have "null" wouldn't you just have to replace it with something else?