3

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?

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
djh
  • 93
  • 5
  • Scheme and Common Lisp are different languages, but you may find ['(quote quote) in scheme](http://stackoverflow.com/q/12520835/1281433) useful, since the issue is the same. A few more relevant links (and possible duplicates) can be found in [this comment](http://stackoverflow.com/questions/24342351/how-to-explain-scheme-expression-a-b#comment37634123_24342351). – Joshua Taylor Aug 13 '15 at 16:09

2 Answers2

5

'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)
Sylwester
  • 47,942
  • 4
  • 47
  • 79
3

Note that a REPL (the READ-EVAL-PRINT-LOOP) does three things:

  • reading using the function READ
  • evaluating using the function EVAL
  • and printing the result using something like the function PRINT

To understand what is going on you have to look at all three functions.

Let's look at the third form:

(list 'quote 1 2 3)

This is read as a list of five elements:

  1. LIST
  2. (QUOTE QUOTE)
  3. 1
  4. 2
  5. 3

EVAL then evaluates the arguments, and calls the function list with the four results and returns a new result, a list of four elements:

  1. QUOTE
  2. 1
  3. 2
  4. 3

PRINT then takes this list and writes it as: (QUOTE 1 2 3). There is no abbreviated way to print it.

Let's look at the fourth form:

(list 'quote '(1 2 3))

This is read as a list of three elements:

  1. LIST
  2. (QUOTE QUOTE)
  3. (QUOTE (1 2 3))

eval calls list with two arguments:

  1. QUOTE
  2. (1 2 3)

eval then returns a list of length two:

  1. QUOTE
  2. (1 2 3)

print now can print this list in two different ways:

(QUOTE (1 2 3)) or the abbreviated form '(1 2 3). Here a quote character is in front of a single expression.

Your implementation used the first version.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346