2

Why does the expression

('+ 10 20) 

evaluate to 20? This is realy bizarre to me! I would have expected to give an error, because the first element of the list, '+ i not a thing that can be evaluated!

0

1 Answer 1

8

This is pretty much an FAQ with Clojure, for good or bad. So '+ is shorthand for (quote +) which evaluates to the symbol +. Symbols (and keywords) can be treated as functions and look themselves up in their argument, so ('+ 10 20) is essentially (get 10 '+ 20) and that's the not-found arity of get so if the "collection" 10 does not include the symbol '+ then it will return the third argument, 20.

You might expect associative lookup against 10 to fail and throw an exception but there are a lot of situations in Clojure where lookup will return nil (or the not-found version) because it's beneficial from a nil-punning point of view and is part of what leads to idiomatic Clojure.

Some functions do perform that sort of argument checking: (contains? 10 '+) will throw an exception, for example, whereas both (get 10 '+) and (get '+ 10) will both return nil.

It's probably also worth noting that the following throws an exception:

user=> ('+ 10 20 30) Execution error (ArityException) at user/eval39476 (REPL:1). Wrong number of args (3) passed to: clojure.lang.Symbol 

You asked if the "value of a list with quoted first argument in clojure is the last argument" and the answer is no, this is very specifically a two-argument function invocation, because of the above logic: you can't "call" a symbol with 3 args, only with 1 or 2.

Worth noting the difference here for the 0 args case:

user=> ('+) Execution error (ArityException) at user/eval39478 (REPL:1). Wrong number of args (0) passed to: clojure.lang.Symbol user=> (+) 0 

The first case is a symbol lookup -- which requires at least a collection to look itself up in -- whereas the second case is a function invocation (of clojure.core/+) with zero arguments, which returns the identity value of + in the same way that (*) returns 1.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the extremely detailed explanation. I had no idea.
Thanks! This was very helpful. Is this written down somewhere in the docs (an FAQ section, perhaps?)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.