Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure first and rest

Why do I get 2 different values for

(apply (first '(+ 1 2)) (rest '(+ 1 2)))
> 2

and

(apply + '(1 2))
> 3

when

(first '(+ 1 2)) 
> +

and

(rest '(+ 1 2))
> (1 2)

I tried reduce and got the same value

(reduce (first '(+ 1 2)) (rest '(+ 1 2)))
> 2
like image 340
KobbyPemson Avatar asked Dec 27 '22 23:12

KobbyPemson


2 Answers

Your trouble is that you're trying to call the symbol '+ rather than the function +. When you call a symbol, it tries to look up the symbol in the first argument (for example, if it had been {'a 1 '+ 5 'b 2} you would have gotten 5). If you pass a second argument, that value gets returned instead of nil if the symbol can't be found in the first argument. So when you call ('+ 1 2), it tries to look up '+ in 1 and fails, so it returns 2.

Incidentally, this is the difference between creating lists with '(+ 1 2) and (list + 1 2). The former creates a list of the symbols +, 1 and 2. Since '1 and 1 are the same, that's fine. But the symbol '+ is not the Var clojure.core/+, so the latter gets the value of the Var while the former just gets the symbol. So if you'd done (list + 1 2), your could would have worked as written.

like image 59
Chuck Avatar answered Jan 06 '23 01:01

Chuck


(first '(+ 1 2)) is a symbol.

user=> (class (first '(+ 1 2)))
clojure.lang.Symbol
user=> (apply (symbol "+") [1 2])
2
user=> (apply (eval (symbol "+")) [1 2])
3
user=> (apply (eval (first '(+ 1 2))) (rest '(+ 1 2)))
3

user=> (class (first [+ 1 2]))
clojure.core$_PLUS_
user=> (apply (first [+ 1 2]) (rest '(+ 1 2)))
3
like image 43
number23_cn Avatar answered Jan 06 '23 03:01

number23_cn