Gem #23: Null Considered Harmful

by Bob Duff —AdaCore

Let's get started…

Ada, like many languages, defines a special 'null' value for access types. All values of an access type designate some object of the designated type, except for null, which does not designate any object. The null value can be used as a special flag. For example, a singly-linked list can be null-terminated. A Lookup function can return null to mean "not found", presuming the result is of an access type:

   type Ref_Element is access all Element;
   Not_Found : constant Ref_Element := null;
   function Lookup (T : Table) return Ref_Element;
   --  Returns Not_Found if not found.

An alternative design for Lookup would be to raise an exception:

   Not_Found : exception;
   function Lookup (T : Table) return Ref_Element;
   --  Raises Not_Found if not found.
   --  Never returns null.                  <--  Ada 95 comment.

Neither design is better in all situations; it depends in part on whether we consider the "not found" situation to be exceptional.

Clearly, the client calling Lookup needs to know whether it can return null, and if so, what that means. In general, it's a good idea to document whether things can be null or not, especially for formal parameters and function results. In Ada 95, we do that with comments. In Ada 2005, we can use the "not null" syntax:

   function Lookup (T : Table) return not null Ref_Element;  --  Ada 2005

In general, it's better to use the language proper for documentation, when possible, rather than comments, because compile-time and/or run-time checks can help ensure that the "documentation" is actually true. With comments, there's a greater danger that the comment will become false during maintenance, and false documentation is obviously a menace.

In many, perhaps most, cases, null is just a tripping hazard. It's a good idea to put in "not null" when possible. In fact, a good argument can be made that "not null" should be the default, with extra syntax required when null is wanted. This is the way SML works, for example -- you don't get any special null-like value unless you ask for it. Of course, Ada 2005 needs to be compatible with Ada 95, so "not null" cannot be the default for Ada.

One word of caution: access objects are default-initialized to null, so if you have a "not null" object (or component) you had better initialize it explicitly, or you will get Constraint_Error. "Not null" is more often useful on parameters and function results, for this reason.

Related Source Code

Ada Gems example files are distributed by AdaCore and may be used or modified for any purpose without restrictions.