On 2011-11-03, fortunatus <
daniel....@excite.com> wrote:
> I find the basic concept a little odd in itself:
>
> CL-USER> (symbolp 'nil)
> T <-- no sweat
> CL-USER> (symbolp nil)
> T <-- kind of freaky...
CL-USER> nil
NIL
CL-USER> 'nil
NIL
The object nil, when treated as program syntax to be evaluated,
evaluates to itself, nil. So nil and (quote nil) is the same.
(QUOTE X) and X is the same thing for any X which evaluates to itself!
Thus this is the case for most atoms, and some kinds of symbols. The symbol T,
and keyword symbols:
CL-USER> 5
5
CL-USER> '5
5
CL-USER> 'T
T
CL-USER> T
T
CL-USER> ':keyword-x
:KEYWORD-X
CL-USER> :keyword-x
:KEYWORD-X
> CL-USER> (symbolp '( ))
> T <-- this freaks me out!!
Note how the unquoted case freaks you out when you use nil,
and the quoted case freaks you out when you use (). Haha!
Since empty list is represented by the symbol NIL, symbolp has to return
T for an empty list.
> A list is not a symbol but the empty list is a symbol?!! The nothing-
A list is not an encapsulated container of stuff like in some languages. It is
recursively defined as one of two things:
1. The symbol nil, denoting an empty list
2. A cons cell, with the first element of the list in CAR, and
a list of the remaining elements in CDR.
(A cons cell which has something other than a list in CDR is called
an "improper list".)
So you cannot have an operation like
(list-append list new_element)
unless list-append is an operator rather than a function. You cannot turn a
list stored in a location L from empty to non-empty without overwriting the
location L with a new object:
(setf L (cons 1 L)) ;; prepend 1 to list L.
The above can be done using a standard macro:
(push 1 L) ;; expands to something similar to (setf L (cons 1 L)).
The container's identity changes!
This is an important feature in Lisp because of this:
(let* ((list1 '(1 2 3))
(list2 (cons 0 list1))
(list3 (cdr list1)))
(values list1 list2 list3))
We can prepend to a list, or remove the first item from a list,
without modifying it in any way. (In fact the literal list '(1 2 3)
cannot be modified without invoking undefined behavior!)
The expressions which initialize list2 and list3 just perform some
pointer manipulations: allocate a cons cell, and stuff the existing
list into the CDR, thereby obtaining a longer list; or retrieve
the CDR of the original list to obtain a suffix of it shortened
by one item.
In Lisp, a lot of computation is done using lists, whereby old lists are turned
into parts of new lists, without a lot of unnecessary copying going on.
Recursion on list structures takes place without copying cells
thereby creating garbage.
> value is a symbol?
It's not a nothing value. It's an empty list value which also serves
as a boolean false.
To obtain a nothing value, call the function VALUES with no arguments:
CL-USER> (values)
But, alas, even that is a symbol:
CL-USER> (symbolp (values))
T
:)
This is because if the expression (values) is used in a context
that requires a value, like a function argument, a default value
of NIL is supplied.