首页 > 解决方案 > 将函数列表传递给 clojure 中的“map”给出 nil

问题描述

我正在尝试一些clojure的例子。

(def sum #(reduce + %))

(def avg #(/ (sum %) (count %)))

(defn stats
  [numbers]
  (map #(% numbers) '(sum, avg)) ;;works when it is [sum avg]
  )

当我调用 stats 函数时

 (stats [1 24  235 34511 0 14])

它返回(nil nil)。但是,如果我更改注释中提到的代码,它会返回预期的输出。

(34785 11595/2)

为什么函数不能作为列表传递?

标签: clojure

解决方案


您可以将集合参数中的函数传递给map,但'示例中的前缀是引用列表,因此内容是符号 sumavg不是

'(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

'是 的简写quote

未加引号的列表文字被特殊处理。Clojure 将不带引号的列表文字解释为调用,其中列表中的第一个元素指的是被调用的内容。例如,这将调用sum函数,将avg函数作为第一个参数传递(这不起作用):

(sum avg)

通过对带引号和不带引号的列表map执行 pingtype函数,我们可以看到列表元素类型的差异:

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

这是关于引用的另一个广泛答案:在 Clojure 中使用引用


推荐阅读