Live data from Hacker News

What is wrong with NULL

lucidchart.com

131–140 of 147 posts

Re: What is wrong with NULL

#133
I've never had a problem with NULL as a "value". Null is the absence of content, a container that is truly empty, and that is frequently useful. As an example it allows you to differentiate between a numerical field that was never populated vs. one specifically set to Zero. This is often an important distinction.

Re: What is wrong with NULL

#134
post #130

Earlier quoted context omitted.

Sorry, no. You can only pass a stable, property typed Python representation of your left elbow, or the magic unicorn, not the elbow or unicorn itself.

If it quacks like a unicorn then it's still a duck

Unicorn? Une corne?

Ceci n'est pas une corne.

Sometimes a horn is just a cigar.

Re: What is wrong with NULL

#135
post #35

C++ introduced non-null references. But they didn't enforce them. There are still "I'm so l33t I can use null references" people. The new move semantics use null references for things moved from. C++ is trying to do Rust-like borrow checking without a borrow checker. Errors result in de-referencing null and crashing. Rust doesn't have null, but it has Option , which is often syntactic sugar for null. It's not that nu…

The new move semantics use null references for things moved from. No. When you move the contents out of somewhere like an std::vector instance, that object is left in an undefined but valid state. You're free to continue working with that object (though the only meaningful thing you can usually do without undefined behaviour is destruction or the equivalent of clear ). That's very different from null references.

Right; you can't have an array of references, and it's "unique_ptr", not "unique_ref". But pointers do get set to null.

If p1 is a unique_ptr, and you do

    p2 = std::move(p1);
p1's pointer is set to null. Further uses of p1 will fail, or crash, or something.

    p1.get()
returns the underlying pointer or null, apparently escaping the unique_ptr protection.

It's far inferior to Rust's borrow checker.

Re: What is wrong with NULL

#136
post #9

The mistake is an unsafe null: making every object type carry a value in its domain which says "Oops, though my type says I'm a Foobar, I'm not actually an object, la la la! Have a free exception on me, in your face!" Lisp's NIL is brilliant. It's in its own type, the null type! And it's the only instance of that type. No other type has a null instance. Null references in the language simply reflect the tension betwe…

Though the philosophy is different, I'm not sure I see an advantage for NIL when you just look at the effect it has on a programmer's code. You can still have a "NULL-pointer dereference" in CL, except the error is rephrased as "SYSTEM::%STRUCTURE-REF: NIL is not a structure of type X" or whatever. And you still have to have "(if (not (null x)) ...)" which doesn't do much for you, regardless of the underlying theory.

Nope. You have choices:

  (defmethod quack ((foo string))
    ... ;; foo is never anything but a string here. 
    ... ;; definitely not nil!
    )

  (defmethod quack ((foo null))
    ... ;; foo is definitely nil here
    )
Unlike in languages where you have a String reference that can be null, a CLOS method parameter specialized to a string cannot be NIL!

We can also have this piece of minimalism, quite often recurring in Lisp code:

   ;; yield x if it is not nil, else yield y
   (or x y)
Or play hardball:

  ;; if calculation signals an error,
  ;; catch it and keep going
  (ignore-errors (calculation x))
After programming in Lisp for a while you would never write:

  (if (not (null x)) ...)
because it is verbose way of expressing:

  (if x ...)
Every value is its own test for non-nullness, since every value is a generalized boolean which stands for falsehood if it is nil, and truth otherwise.

Re: What is wrong with NULL

#138

Earlier quoted context omitted.

This is not contrived. (1) A cache returns something or NULL. It's generic; i.e. implementation doesn't care what it is storing: integers, strings, etc. (2) A particular value of interest may be NULL or non-NULL. But now I can no longer use my generic cache and my values of interest together. A very real example of this is Java's Map interface. It's completely up to implementation on how they handle null, making inte…

You're conflating the meaning of NULL in that case. That's not a problem of NULL, you're using NULL to represent multiple different things. You can use exceptions to handle that scenario. cache = {} getFromCache = (key) -> return cache[key] if cache[key]? throw "not found" doSomethingWithValue = (key) -> try value = getFromCache(key) catch value = getValueFromNonCache(key) return _doSomethingWith(value)

You can, but resorting to exceptions for what may not be an exceptional circumstance is a workaround for not being able to think of a way to communicate results correctly through the return value. Which illustrates the need here as effectively as the ambiguous use of null in the article.

Re: What is wrong with NULL

#139
post #89
post #34

It's worth noting that having a NULL, somewhere, is not so much a problem as forcing types to have a NULL. In this respect, e.g. Python and Rust both get it right: while Python has a None, and Rust has std::ptr::null(), an object that is a string cannot be any of those, because those are different types (NoneType and raw pointer, respectively). C's problem is that a string could be null, and there's no syntax for a n…

You can get a None type when you are expecting a String type... that is exactly the bug they are talking about. The fact that Python makes this problem BIGGER by allowing other types as well doesn't make it less bug prone.

Except the language is designed around this - for example, trying to get a value from a dictionary in Python doesn't return `None` if it doesn't exist, it throws an exception.

I'm not saying static typing has no value, but there are benefits to dynamic typing, and Python embraces its dynamic typing and is designed around it, so none of the problems given in the article really apply.

Re: What is wrong with NULL

#140

The mistake is an unsafe null: making every object type carry a value in its domain which says "Oops, though my type says I'm a Foobar, I'm not actually an object, la la la! Have a free exception on me, in your face!" Lisp's NIL is brilliant. It's in its own type, the null type! And it's the only instance of that type. No other type has a null instance. Null references in the language simply reflect the tension betwe…

Well, except that the Lisp's NIL (and Python's None) only works with dynamic types, where you never had any kind of guarantee to start with. C and Haskell for example have a void type, that is not null, and in Haskell has a value. But a static void is completely different from a null.

Dynamic types in fact provide something which qualifies as a guarantee. If properly implemented, they prevent an incorrectly typed operation from being applied to a value, which would otherwise result in nonportable, unpredictable or fatal consequences, possibly without any diagnostic. Dynamic types, in an of themselves, do this at the last possible moment. Dynamic typing doesn't preclude the application of static checking with type inference and/or optional declarations, however.
Post reply on HN