Some output from the CLISP REPL:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
The first three, I understand exactly what's going on: The list
function is passed a symbol ('list
or 'quote
) and so the result is a list that begins with the list
or quote
symbol. It's the fourth that confuses me. Why doesn't it return (QUOTE (1 2 3))
?
I realise that if you enter (QUOTE '(1 2 3))
into the REPL, you get '(1 2 3)
back, so the expression are equivalent in that sense. But (LIST 1 2 3)
is equivalent to (1 2 3)
, and yet the first expression doesn't return that.
It seems inconsitent that (list 'quote 1 2 3)
returns a list with the first item being a quote
symbol, but (list 'quote (1 2 3))
returns a quoted list. Especially since expressions like (list 'list ...)
seem to always return a list beginning with the symbol - so far, at least, quote
is the only 'special case' like this.
It's not the easiest question to articulate, so I'm hoping I've managed to get my confusion across. Can anyone explain why quote gets treated in this seemingly-unique way?
'something
is the same as (quote something)
for the lisp reader. Even when nested it will be the case. The next expressions I will double quote so that after evaluation one of the quotes are still in there.
When printing the implementations can choose what to output where there are several possible representations, so some implementations would print the evaluation of ''something
as
(quote something)
while others may use the abbreviation 'something
.
'(quote 1 2 3)
cannot be abbreviated since a quoted form only has one argument. Thus here both lisp systems would print (quote 1 2 3)
.
Here is a way to look at your last expression:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
This will either evaluate to "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)"
or "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)"
.
Since the printer never sees if the input is abbreviated and the data has the same structure in memory the output is never affected by how you input the data. Thus (quote (quote (1 2 3)))
will print the same as ''(1 2 3)
.
You have the same behaviour with cons
cells but the standard dictates how the rules are. (cons 1 (cons 2 (cons 3 '())))
would be (1 . (2 . (3 . ())))
but is actually just printed (1 2 3)
However if you (cons 1 2)
you get (1 . 2)
showing that print
treats the output differently based on the cdr
. However the reader can read any of these and they will all print the same eg. '(1 . (2 . (3 . ()))) ==> (1 2 3)
and (+ . (2 . ( 3 . ()))) ; ==> 5
Numbers can have as many visual forms as there are bases below the number in question.
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list
does not have any abbreviation or specialness in Lisp. It's not even a primitive function but it's very helpful as it removes the inconvenience of having to cons by hand everytime. It can be defined like this:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)