Clojure减少函数

时间:2018-05-19 14:25:06

标签: clojure

我试图从clojuredocs.org中了解这个功能:

;; Create a word frequency map out of a large string s.

;; `s` is a long string containing a lot of words :)
(reduce #(assoc %1 %2 (inc (%1 %2 0)))
    {}
    (re-seq #"\w+" s))

; (This can also be done using the `frequencies` function.)

我不明白这一部分:(inc(%1%2 0))

3 个答案:

答案 0 :(得分:3)

这是一个更易于理解的同一个例子,不使用匿名函数语法:

(reduce
  (fn [acc elem]
    (assoc acc elem (inc (acc elem 0))))
  {}
  (re-seq #"\w+" "a dog a cat a dog a banana"))
=> {"a" 4, "dog" 2, "cat" 1, "banana" 1}

此处acc是我们正在构建的地图,elem是当前的字词。让我们分解(inc (acc elem 0))

  1. inc将增加内部表达式返回的数字
  2. (acc elem 0)get来自acc地图的当前数字elem,如果没有数字,则会返回{{1} }}。这是0的缩写 - 地图也是函数,行为类似于(get acc elem 0)函数。
  3. 您还可以使用get获得与(assoc acc elem (inc (acc elem 0)))相同的效果。

    使用带编号参数的匿名语法替换reduce函数时,同样的逻辑适用。

答案 1 :(得分:2)

传递给%1的函数的第一个参数(匿名函数中的reduce)是累加器,最初是作为第二个参数传递给{{}的空映射{}。 1}}。映射是查找给定键的值的函数,如果未找到键,则返回可选的默认值,例如

reduce

({"word" 1} "word") = 1

所以

({"word" 1} "other" 0) = 0

在累加器映射中查找当前单词(缩减函数的第二个参数)的计数,如果尚未添加单词,则返回0。 (%1 %2 0) 增加当前计数,所以

inc

增加中间地图中当前单词的计数,或者如果这是第一次遇到该单词,则将其设置为1.

答案 2 :(得分:1)

您要问的代码基本上是that of the standard frequencies function,其中transients已删除:

(defn frequencies [coll]
   (reduce
     (fn [counts x] (assoc counts x (inc (get counts x 0))))
     {}
     coll))