Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply a list of function to parameter, clojure

Tags:

clojure

(def ops '(+ - * /))
(map #(% 2 5) ops)

gives

(5 5 5 5)

This doesn't make sense to me. Why does this return a list of 5 instead of results of function calls?

like image 728
user40129 Avatar asked Apr 24 '15 16:04

user40129


3 Answers

This works: (map #(% 2 5) [+ - * /])

This does not: (map #(% 2 5) '[+ - * /])

Nor does this: (map #(% 2 5) '(+ - * /))

The reason is that when you do '(+ - * /), you get a list of the symbols +, - * and /, not the functions to which they refer - the quote also applies to the values of the list.

Using a vector avoids this problem.

If you absolutely want a list, do (map #(% 2 5) (list + - * /)).

like image 200
bsvingen Avatar answered Nov 14 '22 00:11

bsvingen


The problem is that '(+ - * /) is a list of symbols, not a list of functions. Symbols implement AFn and when supplied with two arguments, the function attempts to look up the symbol in the first argument (2 here) and returns the second argument (5 here) if the lookup fails.

like image 28
Lee Avatar answered Nov 14 '22 00:11

Lee


There is a function in clojure that does exactly what you want: juxt: http://clojuredocs.org/clojure.core/juxt

So your example would be

(def funcs (juxt + - * /))
(funcs 2 5)

If someone comes up with a good explanation why the map approach does not work I would like to hear that too.

like image 4
sveri Avatar answered Nov 14 '22 01:11

sveri