Reputation: 20618
Here is my code:
(format t "~a~%" (list 1 2 3 4))
(format t "~a~%" '(1 2 3 4))
(format t "~a~%" (remove-if-not #'evenp (list 1 2 3 4)))
(format t "~a~%" (remove-if-not #'evenp '(1 2 3 4)))
Here is the output:
$ clisp bar.lisp
(1 2 3 4)
(1 2 3 4)
(2 4)
(2 4)
My questions:
(list 1 2 3 4)
and '(1 2 3 4)
?Upvotes: 1
Views: 515
Reputation: 9865
The difference between '(1 2 3 4)
and (list 1 2 3 4)
which seem to return absolutely the same result (1 2 3 4)
is not visible, because numbers in Lisp evaluate to themselves.
Instead of numbers take symbols or expressions:
(list (+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5))
;; returns/evaluates to:
(3 5 7 9) ;; each of the arguments in a list gets evaluated.
;; while:
'((+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5)) ;; equals to: (quote ((+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5)))
;; returns/evaluates to:
((+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5)) ;; arguments of list not evaluated
;; since `quote` means: take the argument as data - unevaluated.
Now you see clearly the difference: '(1 2 3 4)
expanding to (and thus is syntactic sugar to) (quote (1 2 3 4))
is a special form, while (list 1 2 3 4)
is a function. Functions in Lisp evaluate each of their arguments. But special forms don't evaluate each of their arguments. In the case of quote
, the argument of quote
is not evaluated.
And now you see, with a
, b
, c
, d
not defined before, this
'(a b c d)
;; returns: (A B C D)
works, since a b c d are not evaluated!
But this:
(list a b c d)
causes an error:
*** - SYSTEM::READ-EVAL-PRINT: variable A has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of A.
STORE-VALUE :R2 Input a new value for A.
ABORT :R3 Abort main loop
because neither a
nor b
nor c
nor d
are yet defined but the Lisp interpreter tries to evaluate them, since they are function arguments.
But you still can get (A B C D)
using the function list
by quoting each of the arguments - thus making them evaluate to their symbol names instead of the Lisp interpreter to lookup their undefined values:
(list 'a 'b 'c 'd)
;; now it works - though a b c d are not defined yet:
(A B C D)
Note: Interestingly, not in all languages, function arguments get evaluated, just because they are function arguments. While Python evaluates all of its function arguments similar to Lisp before entering and evaluation of the function body, R doesn't.
So the evaluation of function arguments is a Lisp-specific way to handle its function arguments. (But it shares it with most of the other languages - I just want to say the evaluation of function arguments is not a general rule). And that is also the fundamental difference between Lisp macros (and special forms) and Lisp functions. In Lisp macros (and special forms), you can specify which of the function arguments get evaluated in the macro body and which not. So that you have full control over evaluation of any of the macro arguments. In Lisp functions, by default, all arguments first get evaluated before you enter the function body.
That is also one of the reasons why you have also to learn macros (which specify special forms) in Lisp. quote
together with list
is actually the mother of all macros. Any backquote
and unquote
operations can be expressed by quote
and list
(though looking nastier for the human reader). One could ponder quite long about this topic, as you can imagine. And your question goes directly into the heart and essence of what makes Lisp so fascinating.
Upvotes: 3
Reputation: 51501
The difference is when the list gets created. One is created by the reader, the other at runtime.
The reader is responsible for turning your text file into a data structure representing code. This data structure happens to be mostly lists; this is the idea of Lisp (LISt Processing).
When the reader reads the text (foo bar)
, it creates a list of two elements, namely the symbols foo
and bar
. This is then compiled, i. e. translated, into a function call (or other call, but let's not divert here), where the function named by foo
is called with with the value of the variable named by bar
.
There is a special operator that tells the compiler not to do this translation: quote
. When the compiler encounters the list (constructed by the reader) (quote (foo bar))
, it uses the thing „protected“ by quote
literally, i. e. exactly that list (foo bar)
constructed by the reader.
The apostrophe '
is a shorthand for quote
, so '(foo bar)
is read as (quote (foo bar))
.
The form '(1 2 3)
is thus exactly the list that you wrote into your text file, as read by the reader. This is called a literal list.
On the other hand, (list 1 2 3)
is a normal function call of the function list
with three arguments. It creates a new list of these arguments any time this code is executed at runtime.
You should use a literal list only if it is constant. For example, when creating a multidimensional array, you might know its size is always the same (maybe it is intrinsic to the problem), so you write (make-array '(3 5))
. If you want to make it configurable, you parameterize it: (make-array (list width height))
.
One thing you absolutely must avoid is modifying literal data.
Upvotes: 1