我正在尝试一些Clojure的例子。
(def sum #(reduce + %))
(def avg #(/ (sum %) (count %)))
(defn stats
[numbers]
(map #(% numbers) '(sum, avg)) ;;works when it is [sum avg]
)
Run Code Online (Sandbox Code Playgroud)
当我调用统计功能
(stats [1 24 235 34511 0 14])
Run Code Online (Sandbox Code Playgroud)
它返回(nil nil)。但是,如果我按注释中所述更改代码,它将返回预期的输出。
(34785 11595/2)
Run Code Online (Sandbox Code Playgroud)
为什么不能将函数作为列表传递?
您可以将collection参数中的函数传递给map,但是'示例中的前缀是引用列表,因此内容是符号 sum而avg不是value。
'(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
Run Code Online (Sandbox Code Playgroud)
'是的简写quote。
未引用的列表文字会被特别对待。Clojure将未加引号的列表文字解释为调用,列表中的第一个元素指的是被调用的内容。例如,这将调用该sum函数,并将该avg函数作为其第一个参数传递(这将不起作用):
(sum avg)
Run Code Online (Sandbox Code Playgroud)
通过对带引号和不带引号的列表执行mapping操作type,我们可以看到列表元素类型的不同:
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
Run Code Online (Sandbox Code Playgroud)
这是关于报价的另一个广泛的答案:在Clojure中使用报价