The difference between different Lisps is how they handle true, false and nil.
In Common Lisp, we have t
for true, and nil
for false, although everything except nil
is in fact true. Where the list is empty, or a find
found nothing, we have nil
and we can test directly. The technical term is nil punning
.
'() ; => NIL
(= 1 2) ; => NIL
(if '() "full" "empty") ; => "empty"
(find 5 '(1 2 3 4)) ; => NIL
(if (find 5 '(1 2 3 4)) "found" "not found" ; => "not found"
Clojure does it differently. There is one official true value true
, and there are two false values, false
and nil
- all values other than false
and nil
are also true. The empty list is no longer nil
, and you need to use a separate test for an empty list, with empty?
. The value nil
is more like void
in C. Better or worse? - you decide.
'() ; => ()
(= 1 1) ; => true
(= 1 2) ; => false
(if '() "full" "empty") ; => "full"
(if (empty? '()) "empty" "full") ; => "empty"
(if nil "full" "empty") ; => "empty"
(if (println "Hello world") "full" "empty") ; => empty
Scheme is much closer to Clojure in intent. Here there is one false value, #f
. The empty list is no longer nil
, and you need to use a separate test for an empty list, with null?
.
(= 1 1) ; => #t
(= 1 2) ; => #f
(null? '()) ; => #t
(null? 'nil) ; => #f
So, null
is another name for the empty list, but nil
or 'nil
is not.
null ; => ()
nil ; => cannot reference an identifier before its definition
'nil ; => nil
How about (car ())
? Your Scheme returns nil
from evaluating ()
, and that is what car
is complaining about. My Scheme, Dr Racket, refuses to play at all, saying that the expression is missing from the empty list.