2017-07-15 89 views
0

我是clojure的新手,并在clojure文档中注意到此示例。Clojure:具有减少的匿名函数

(reduce (fn [m [k v]] (assoc m v k)) {}{:b 2 :a 1 :c 3})

输出:;;=> {2 :b, 1 :a, 3 :c}

可有人背后的代码的逻辑解释?

+1

您认为这意味着什么?你有什么零件有麻烦? – amalloy

+0

'{} {:b 2:a 1:c 3}' – Srini

+0

@ user1702169将这两幅贴图“粘”在一起这样并不真正有帮助(除非你是代码打高尔夫球)。把它写成“{} {...}”,这将是明确的,那是两件不同的事情。 – cfrick

回答

4

reduce将函数应用于累加器和序列中的每个元素,以建立最终结果。 ClojureDocs给出the signature for reduce(reduce f coll)(reduce f val coll)。您的示例具有与元件匹配后者签名如下:

  • f:函数应用到每个条目,(fn [m [k v]] ...
  • val:初始累加器,{}
  • coll:操作上收集, {:b 2 :a 1 :c 3}

请注意,reduce调用的第二个参数和第三个参数之间没有分隔符(即空格)。 Clojure不需要一个。

然后,看看内部的匿名函数:(fn [m [k v]] (assoc m v k))。第一个参数m是累加器的当前值,其在减少开始时为{}Destructuring syntax用于第二个参数,它是要修饰的当前值,即一个映射条目。地图条目被拆解为其关键字k并且值v。匿名函数的主体只是向累加器(即map)放入一个新的“反向”条目,以便原始序列v的值是关键字,关键字k成为该值。结果类似于应用Clojure API函数map-invert

请注意,有一个单独的reduce-kv函数用于减少关联集合(例如,地图)。 reduce-kv“为你解构”。这允许将被写入的匿名功能:

(fn [m k v] (assoc m v k)) 

或者甚至更简单地与短符号:

#(assoc %1 %3 %2) 
0

第一个映射是空的,它是一个可选的初始化值,它是传递给reduce函数的第一个参数。第二张地图是要减少项目的集合。在这种情况下,每个项目是MapEntry,并且它们作为第二个参数一次传递给还原函数。

鉴于您的输入地图有三个键/值对,缩减功能将被调用三次。减号函数的参数m参考第一次调用时的初始化值(空映射)和分解第二个参数k and v来自在迭代中传递的MapEntry对。

尽管大多数时候reduce函数在第一个参数被操作后返回第一个参数,但在您的示例中,它将第二个参数的键/值颠倒并将新对与初始化值相关联,这样做..

0

这意味着reduce地图{:b 2 :a 1 :c 3}与功能(fn [m [k v]] (assoc m v k))其依次取一个键 - 值对[k v]从地图上把它和accumulator hash-map m关联。累加器散列映射的初始状态设置为空({})。