I am trying out a few examples of clojure.
(def sum #(reduce + %))
(def avg #(/ (sum %) (count %)))
(defn stats
[numbers]
(map #(% numbers) '(sum, avg)) ;;works when it is [sum avg]
)
When I call stats function
(stats [1 24 235 34511 0 14])
it returns (nil nil)
. But if I change the code as mentioned in the comment it returns the expected output.
(34785 11595/2)
Why can't functions be passed as a list?
You can pass the functions in the collection argument to map
, but the '
prefix in your example is quoting the list, so the contents are the symbols sum
and avg
instead of the values.
'(sum avg) ;; quoted list, contents are symbols
'[sum avg] ;; quoted vector, contents are symbols
(list sum avg) ;; list of the functions, using `list` fn to create a list
[sum avg] ;; vector of the functions
'
is a shorthand for quote
.
Unquoted list literals are treated specially. Clojure interprets an unquoted list literal as an invocation, where the first element in the list refers to what's being invoked. For example, this would invoke the sum
function, passing the avg
function as its first argument (which won't work):
(sum avg)
By map
ping the type
function over quoted and non-quoted lists, we can see the difference in types of the list elements:
user=> (map type '(conj assoc))
(clojure.lang.Symbol clojure.lang.Symbol) ;; symbols
user=> (map type (list conj assoc))
(clojure.core$conj__5112 clojure.core$assoc__5138) ;; fn values
Here's another extensive answer on quoting: Using quote in Clojure