←back to thread

Hofstadter on Lisp (1983)

(gist.github.com)
372 points Eric_WVGG | 2 comments | | HN request time: 0.41s | source
Show context
susam ◴[] No.41861244[source]
> Attempting to take the car or cdr of nil causes (or should cause) the Lisp genie to cough out an error message, just as attempting to divide by zero should evoke an error message.

Interestingly, this is no longer the case. Modern Lisps now evaluate (car nil) and (cdr nil) to nil. In the original Lisp defined by John McCarthy, indeed CAR and CDR were undefined for NIL. Quoting from <https://dl.acm.org/doi/pdf/10.1145/367177.367199>:

> Here NIL is an atomic symbol used to terminate lists.

> car [x] is defined if and only if x is not atomic.

> cdr [x] is also defined when x is not atomic.

However, both Common Lisp and Emacs Lisp define (car nil) and (cdr nil) to be nil. Quoting from <https://www.lispworks.com/documentation/HyperSpec/Body/f_car...>:

> If x is a cons, car returns the car of that cons. If x is nil, car returns nil.

> If x is a cons, cdr returns the cdr of that cons. If x is nil, cdr returns nil.

Also, quoting from <https://www.gnu.org/software/emacs/manual/html_node/elisp/Li...>:

> Function: car cons-cell ... As a special case, if cons-cell is nil, this function returns nil. Therefore, any list is a valid argument. An error is signaled if the argument is not a cons cell or nil.

> Function: cdr cons-cell ... As a special case, if cons-cell is nil, this function returns nil; therefore, any list is a valid argument. An error is signaled if the argument is not a cons cell or nil.

replies(6): >>41861327 #>>41861751 #>>41862379 #>>41862873 #>>41862933 #>>41868929 #
lisper ◴[] No.41862873[source]
> Modern Lisps now evaluate (car nil) and (cdr nil) to nil.

Scheme doesn't. Taking the CAR or CDR of nil is an error.

replies(3): >>41863007 #>>41863233 #>>41868861 #
susam ◴[] No.41863233[source]
Does Scheme even have NIL in the sense that other Lisps like CL or Elisp have? I mean in Common Lisp, we have:

  CL-USER> (symbolp nil)
  T
  CL-USER> (atom nil)
  T
  CL-USER> (listp nil)
  T
Similar results in Emacs Lisp. But in MIT Scheme, we get:

  1 ]=> nil

  ;Unbound variable: nil
Of course, we can use () or (define nil ()) to illustrate your point. For example:

  1 ]=> (car ())

  ;The object (), passed as the first argument to car, is not the correct type.
But when I said NIL earlier, I really meant the symbol NIL that evaluates to NIL and is both a LIST and ATOM. But otherwise, yes, I understand your point and agree with it.
replies(2): >>41863266 #>>41865146 #
lisper ◴[] No.41865146[source]
> Does Scheme even have NIL in the sense that other Lisps like CL or Elisp have?

No. It has an empty list, which is a singleton atomic value whose type is not shared with any other object, and it has a boolean false value, which is distinct from the empty list. A user can create a symbol named NIL, but that symbol has no characteristics that distinguish it from any other symbol. You can, of course, bind NIL to either the empty list or boolean false (or any other value) but it can only have one value at a time (per thread).

replies(1): >>41868328 #
1. blenderob ◴[] No.41868328[source]
> No. It has an empty list

If there is no nil in scheme, what did you mean when you said that taking car or dr of nil is an error in scheme?

replies(1): >>41870464 #
2. lisper ◴[] No.41870464[source]
You need to read more carefully. The claim was not that there is no NIL in Scheme, the claim was that Scheme does not have a "NIL in the sense that other Lisps like CL or Elisp have". There is a NIL is Scheme, but it's just a symbol like any other with no privileged status. Also, in colloquial use, the word "nil" is often taken to be a synonym for "the empty list" even when talking about Scheme.