LWN.net Logo

RE: nullable pointers

RE: nullable pointers

Posted Mar 31, 2011 13:21 UTC (Thu) by HelloWorld (guest, #56129)
In reply to: RE: nullable pointers by neilbrown
Parent article: GCC 4.6.0 released

But when you really want a nullable pointer, as you do in a linked list or any tree data structure
You don't need nullable pointers for linked lists
abstract class List<T> { }
final class ListNil<T> { }
final class ListCons<T> { T elem; List<T> tail; }
or for trees
abstract class BinaryTree<T> { }
final class TreeNil<T> { }
final class TreeCons<T> { T elem; BinaryTree<T> left; BinaryTree<T> right; }
arbitrarily not allowing one seems pointless.
What is arbitrary is a null reference, not the lack of it. What could be more arbitrary than a magical value created out of thin air, which is a value of (almost) every type, yet supports none of the operations that all other values of these types support.


(Log in to post comments)

RE: nullable pointers

Posted Mar 31, 2011 15:45 UTC (Thu) by mister_m (guest, #72633) [Link]

Wouldn't you have bigger problems if you tried to access an element that was filled with garbage values?

RE: nullable pointers

Posted Mar 31, 2011 16:00 UTC (Thu) by HelloWorld (guest, #56129) [Link]

Of course, the compiler must ensure that a variable is never read before it is written. But this is fairly easy to do and does't require null.

RE: nullable pointers

Posted Mar 31, 2011 19:04 UTC (Thu) by mister_m (guest, #72633) [Link]

I am a bit of a novice. Would you mind explaining how I would enable the compiler to do that? I am missing some programming knowlege in this area I think = perhaps a suer defined type? In school, we always set unused pointers to null, and then check for null to see if we can dereference whatever is at the other end.

RE: nullable pointers

Posted Mar 31, 2011 20:36 UTC (Thu) by HelloWorld (guest, #56129) [Link]

> I am a bit of a novice. Would you mind explaining how I would enable the compiler to do that?
Unless you're the one writing the compiler, you can't. Of course, you could just use a language that does this by default, like Haskell or OCaml.

RE: nullable pointers

Posted Apr 12, 2011 16:04 UTC (Tue) by oelewapperke (guest, #74309) [Link]

The essence of the trick is that you simply make a type difference between "filled in" pointers and "null" pointers.

A tree would be defined like so :

abstract class TreeNode {}
abstract class EmptyTreeNode extends TreeNode {}
abstract class FilledTreeNode extends TreeNode {
TreeNode first;
TreeNode second;
}

If you combine this with runtime polymorphism you can do something like this (won't work in Java, but I'm using java code anyway)

void processTreeNode(EmptyTreeNode et) {}
void processTreeNode(FilledTreeNode ft) {
// you might want to do something useful here
processTreeNode(ft.first);
processTreeNode(ft.second);
// or here
}

then simply call processTreeNode(tree), and the compiler would figure out whether to call the first or the second function.

I would love for java to support this though.

RE: nullable pointers

Posted Apr 1, 2011 3:47 UTC (Fri) by neilbrown (subscriber, #359) [Link]

I'm not familiar with the language you are writing in (being primarily a C programmer), but I gather the a variable of type "List<T>" is allowed to refer to either an object of type "ListNil<T>" or an object of type "ListCons<T>". "ListNil<T>" fills exactly the same role a "NULL" so what you have created is exactly a NULLable pointer, only with a different name and more complex syntax.

A rose by any other name still has thorns, and a NULL de-reference by any other name still causes a run-time-exception or worse.

All values are "created out of thin air". They are abstractions which we create and use to try to model "real" things. Values that are useful we re-use. Values that are not, we forget. NULL turns out to be useful.

Your argument against NULL would seem to apply equally to the value '0'. It is an arbitrary magical value - that the Romans seemed to manage with out. It is a value of every (numerical) type, yet it doesn't support being the divisor in a division. We really should eradicate it - that would get rid of all divide-by-zero errors forever.

Of course, divide-by-zero errors are not caused by the availability of a 0 value, but by the misuse of that value. Similarly NULL pointer de-reference errors are not caused by the availability of a 'NULL' value, but by the misuse of that value.

RE: nullable pointers

Posted Apr 1, 2011 4:39 UTC (Fri) by HelloWorld (guest, #56129) [Link]

> I'm not familiar with the language you are writing in
It's Java (though I don't usually use that language).

> "ListNil<T>" fills exactly the same role a "NULL" so what you have created is exactly a NULLable pointer, only with a different name and more complex syntax.
No, it's not the same thing. As was pointed out multiple times by now, null references can show up everywhere, even in places where they don't make sense and where nobody ever intended or expected them to do. On the other hand, ListNil<T> objects are allowed only allowed where lists are allowed, and any sensible program that operates on lists expects those lists to end at some point (in eager languages at least).

> Your argument against NULL would seem to apply equally to the value '0'.
No, 0 isn't something that somebody just made up. If you don't have 0, you can't add two integers as the only sensible result of adding x and -x is 0. So yes, the fact that you can't divide by 0 is a problem, but getting rid of that is hard. No such argument can be made for null.
I also dislike the fact that null mixes up many different concepts that ought to be separate. null was used to represent optional values, empty lists, empty trees and probably all kinds of other things which don't have anything in common.

RE: nullable pointers

Posted Apr 1, 2011 6:06 UTC (Fri) by paulj (subscriber, #341) [Link]

Sure, but you still have a specialised nil type. Whether you use a null reference on a List type to denote the end of the list or a special EmptyList class, it still means your code has to take to check what exactly the reference is pointing to before going through it to avoid a runtime exception.

I don't see how getting a ClassCastException is any better than a NullPointerException. Even though you've created a new type, neither you nor the compiler is any better position...

RE: nullable pointers

Posted Apr 1, 2011 8:22 UTC (Fri) by nybble41 (subscriber, #55106) [Link]

The example was simply to show that you don't need all pointers to be nullable to have linked lists. The advantages for this case are minimal, since linked lists specifically depend on the 'next' pointer being nullable. However, linked lists are a hardly representative of pointers in general, particularly in a language like Java where all objects are accessed via pointers. The benefit of making pointers non-nullable by default is in the majority of cases where nulls are nothing but a source of runtime exceptions.

The advantages tend to be more pronounced in languages like Haskell, however, which have more advanced type systems which handle this sort of subtyping without any need for runtime casts. As you point out, in Java you would need to explicitly cast from List<T> to ListNil<T> or ListCons<T>, an operation which can fail in much the same manner as dereferencing a null pointer.

RE: nullable pointers

Posted Apr 1, 2011 13:33 UTC (Fri) by HelloWorld (guest, #56129) [Link]

> Sure, but you still have a specialised nil type. Whether you use a null reference on a List type to denote the end of the list or a special EmptyList class, it still means your code has to take to check what exactly the reference is pointing to before going through it to avoid a runtime exception.
How many times do you want me to repeat this? The fact that you need a way to represent the empty list does not mean that you need nullable pointers _everywhere_, even where they _don't_ have any purpose (unlike the list case).

RE: nullable pointers

Posted Apr 1, 2011 14:25 UTC (Fri) by paulj (subscriber, #341) [Link]

That isn't what you were arguing earlier though. You have been arguing that nullable types are *always* a bad thing (in a grandparent to this post) and there is *never* a need for them (to paraphrase several other comments of yours).

To my mind, having to go from checking the value of a reference to checking other properties of a composite object (the type, or a length attribute), and still being left open to runtime-exceptions (with a different name) if you forget, means you still are facing fundamentally the same problem.

Can the compiler maybe catch a couple more problems it wouldn't otherwise. Sure. Is it a silver bullet? Sadly, still no.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds