

Do we really need null? - vmathew
http://home.vmathew.in/writings/nonull

======
_delirium
Another possible solution is to _require_ initialization of reference types
upon declaration, instead of silently supplying a new default object if no
initialization is given. A bit more verbose, but might be clearer (esp. in
Java-land, where stuff happening behind the scenes without explicit code is
frowned on).

Ocaml basically does that, though it feels sort of second-nature rather than a
restriction, because syntactically, the only way to get a reference is to take
a reference _of_ something. Eiffel "attached types" are similar (guaranteed to
always be "attached" to a non-Void value), but have a somewhat more complex
scheme of possibilities:
[http://docs.eiffel.com/sites/docs.eiffel.com/files/void-
safe...](http://docs.eiffel.com/sites/docs.eiffel.com/files/void-safe-
eiffel.pdf)

A big potential problem, I think, would be whether people use null-setting
patterns often enough that they would work around the proposed change, by
using these default-constructed objects as glorified null values, maybe by
having them set an "I'm a dummy object" flag internally or something.

------
DCoder
Conditional initialization? Suppose I have several objects of the same type
and need to do manipulations on one of them, which one depends on something:

    
    
      Foo * pFoo = NULL;
      if(x) {
       // stuff
       pFoo = Foo::p1;
      } else {
       // stuff
       pFoo = Foo::p2;
      }
      if(pFoo) {
       pFoo->bar();
      }
    

I can't declare pFoo inside if(x) due to scoping, so I have to declare it
before initializing it meaningfully. It has to be either a pointer to the
object (references don't work without initialization) or an object copy, which
would not modify the original object...

~~~
vmathew
In the first place, a language that exposes pointers may not be able to do
away with null. But as for languages like Java, the problem can be solved with
the help of an implicit, non-mutable default object:

    
    
        Foo foo; // initialized to default
        if (x) {
           // stuff
           foo = Foo.p1;
        } else {
          // stuff
          foo = Foo.p2;
        }
        // No need to check if this is a valid reference, it always will be.
        foo.bar();

------
cperciva
Yes, we really do need NULL. It's very useful in a number of data structures;
for example:

    
    
      struct node {
        char * key;
        char * value;
        struct node * left;   // NULL if we have no left child
        struct node * right;  // NULL if we have no right child
      }
    

Sure, you could add a separate "int flags" field to record which children a
node has, but that would just make the code slower and cause it to use more
RAM.

~~~
vmathew
A systems programming language that expose pointers will not be able to shed
NULL. But a higher-level language can and a "pure" OOP language should -
because null make objects unable to respond to messages. Something that claims
to belong to the type system and cannot respond to messages just don't fit in
there.

~~~
cperciva
Ok, I'll bite: In your idea of a perfect object-oriented language, how do you
encode "we might or might not have a left child"?

~~~
vmathew
This is one possible way of doing it:

    
    
        class Node {
            static const Node EMPTY_NODE = Node();
            String key;
            String value;
            Node left = EMPTY_NODE;
            Node right = EMPTY_NODE;
    
            Node(String key, String value) {
                this.key = key;
                this.value = value;
            }
    
            static void traverseInorder(Node n, Visitor v) {
                if (n.left != EMPTY_NODE) {
                   traverseInorder(left, v);
                }
                v.visit (n);
                if (n.right != EMPTY_NODE) {
                   traverseInorder(right, v);
                }
            }
        }

~~~
cperciva
Ok, and how exactly is that different from using NULL, aside from being more
complicated?

~~~
vmathew

        class Node {
            // May not be a real situation for a Node class,
            // but makes a point.
            Node getLeft() {
                return left;
            }
        }
    
        // No more checks against NULL. In fact code becomes simpler for
        // the user of the library.
        node.getLeft().getLeft().getValue();
    

I don't think the class definition is much too complicated, except for the
declaration of the EMPTY field. What we need is a non-mutable, class-wide,
default object, not null. We don't need to explicitly declare this object, if
the language does that for us and make it accessible through a keyword - say
'default':

    
    
        if (n.left != default) {
             traverse(n.left);
        }

