(list '+ '1 '2)
produces a list of the symbol +
and the numbers 1
and 2
. Evaluating that will look up the function named by the symbol +
and call it with arguments 1
and 2
.
(list + '1 '2)
produces a list of the function named by the symbol +
and the numbers 1
and 2
. Evaluating that will call the function that's already directly an element of the list with the arguments from the rest of the list.
There's never a need to quote numbers, by the way. They're self-evaluating.
EDIT:
The more interesting case which you didn't address in your headline is what happens in the (eval '('+ 1 2))
case? Why does this not return 3
like the other cases that all end up calling the function named by +
with the arguments 1
and 2
?
The answer is that it's different because this time, you have quoted the symbol +
twice. Because of that, the symbol doesn't get resolved to the function it names, instead the symbol itself is called as a function.
Now what is the behaviour when a symbol gets called as a function? It treats its first argument as a map and looks itself up as a key in that map. But the number 1
is obviously not a map, so it would now usually return nil
to indicate that no matching key was found.
In this case though, there's a second argument to the call to the symbol +
, and that second argument gets used as the default value to return when no matching key was found. So that's why the form (eval '('+ 1 2))
returns 2
.
EDIT 2:
OK, and now to finally answer the question: why does quoting a list produce different results than calling the list
function with the same arguments. That's because a quote '
stops all evaluation on the list it's used on, but the list
function evaluates its arguments before producing a list with them as elements.
These differences all becomes very clear when you print the various forms instead of sending them directly to eval
:
user> '(+ 1 2)
(+ 1 2)
user> '('+ 1 2)
((quote +) 1 2)
user> (list '+ '1 '2)
(+ 1 2)
user> (list + '1 '2)
(#<core$_PLUS_ clojure.core$_PLUS_@165c64> 1 2)
You see that the first and third case produce a result that prints the same, because in both these cases you've quoted +
once. In the second case, +
is quoted twice instead, and in the last it isn't quoted at all.
EDIT 3:
One last addition that should hopefully clarify things even further: unless its first element names a macro or special operator, eval
will recursively evaluate all elements of a list (including the first) before evaluating the list itself by calling its (evaluated) first argument as a function with the rest of the list as arguments.
If that first element is '+
or (quote +)
(these are two different ways to write the same thing, the quoted symbol +
), it will evaluate to the symbol +
and that will be called as function.
If the first element is +
, that will evaluate to the the actual addition function (clojure.core$_PLUS_
). If it already is that function, it will stay the same (basically all types besides lists and symbols are self-evaluating). In both cases, eval
will then call that function.