> It is necessary that there be a special empty-list object which is a list but not a cons. That is not true. NIL could be a CONS. In fact, it acts just like a CONS whose CAR and CDR are itself. The only way in which NIL does not behave like a CONS is that it does not answer true to CONSP. But that doesn't matter because it answers true to NULL, so you can build a CL-style CONSP if you want it by checking for (AND (C…
I tend to agree but would be happy to be proven wrong by more knowledgeable folks in these comments. However I assume here we are talking about dotted lists and not ‘proper’ ones?
You can define NIL as follows:
(setf NIL (cons 0 0)))
(setf (car NIL) NIL)
(setf (cdr NIL) NIL)
Then: (defun null (thing) (eq thing NIL))
You also have to add a bunch of special cases to other functions: (defun cl-style-consp (thing)
(and (consp thing) (not (null thing)))
(defun cl-style-symbolp (thing)
(or (symbolp thing) (null thing))
(defun cl-style-symbol-name (thing)
(if (null thing) "NIL" (symbol-name thing)))
and a few others.In fact, many CL implementations actually implement NIL that way so that CAR and CDR of NIL return NIL without having to make that a special case.