Comment by DaleBiagio
11 hours ago
Meyer makes an important point that often gets lost: the null pointer predates Hoare. NIL existed in McCarthy's Lisp in 1959, six years before Hoare added null references to ALGOL W. The "mistake," if it was one, was already widespread.
What made Hoare's 2009 confession so impactful wasn't that he was solely responsible — it's that he was the first person with that level of authority to publicly say "this was wrong."
That's what gave Rust, Swift, and Kotlin permission to design around it.
LISP was special because it had only 2 data types: atoms and lists.
Both lists and atoms could appear in any place in any function or special form.
NIL was a special atom, which was used to stand for an empty list. Because it could appear in any place in a LISP program, it could be used anywhere where one had to write that something does not exist.
In a programming language with a more complicated and also extensible system of data types the handling of "nothing" values must also be more complex.
Any optional type can be viewed as a variable-length array of its base type, whose maximum length is 1 and a null length indicates a non-existent value.
This is equivalent with the use of NIL in LISP.
However, it is better to consider optional types as a distinct method of deriving types from base types than arrays, structures or unions, because in most cases more efficient implementations are possible for optional types than implementing them as variable-length arrays that may have a null length or as tagged unions where one of the alternative types is the empty set (a.k.a. void).
I don’t know much about algol, but in Lisp, nil represents the empty list. And because the list is a recursive data structure, it always contains the empty list. It’s not the same as java where null is its own value that is part of every type. In Lisp, an atom can’t be nil because an atom is not a list.
What you say may be true for some modern LISPs, but it was false in most early LISPs, certainly in any LISP that has preceded the paper "Record Handling" of Tony Hoare.
I quote from the manual of LISP I: "Here NIL is an atomic symbol used to terminate lists".
I am not sure which is the rule in Common LISP, but in many early LISPs the predicate (atom NIL) was true.
In early LISPs, the end of a list was recognized when its CDR was an atom, instead of being another list. The atom could be different from NIL, because that final list could have been an association pair, pointing towards two associated atoms.
The fact that in early LISPs NIL was an atom, but it was also used to stand for an empty list caused some ambiguities.
EDIT: I have searched now and in Common LISP the predicate (atom NIL) remains true, like in all early LISPs, therefore NIL is still an atom, even if using it almost anywhere is equivalent with an empty list.