我是clojure的新手,并在clojure文档中注意到此示例。Clojure:具有减少的匿名函数
(reduce (fn [m [k v]] (assoc m v k)) {}{:b 2 :a 1 :c 3})
输出:;;=> {2 :b, 1 :a, 3 :c}
可有人背后的代码的逻辑解释?
我是clojure的新手,并在clojure文档中注意到此示例。Clojure:具有减少的匿名函数
(reduce (fn [m [k v]] (assoc m v k)) {}{:b 2 :a 1 :c 3})
输出:;;=> {2 :b, 1 :a, 3 :c}
可有人背后的代码的逻辑解释?
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)
第一个映射是空的,它是一个可选的初始化值,它是传递给reduce函数的第一个参数。第二张地图是要减少项目的集合。在这种情况下,每个项目是MapEntry
,并且它们作为第二个参数一次传递给还原函数。
鉴于您的输入地图有三个键/值对,缩减功能将被调用三次。减号函数的参数m
参考第一次调用时的初始化值(空映射)和分解第二个参数k and v
来自在迭代中传递的MapEntry
对。
尽管大多数时候reduce函数在第一个参数被操作后返回第一个参数,但在您的示例中,它将第二个参数的键/值颠倒并将新对与初始化值相关联,这样做..
这意味着reduce
地图{:b 2 :a 1 :c 3}
与功能(fn [m [k v]] (assoc m v k))
其依次取一个键 - 值对[k v]
从地图上把它和accumulator hash-map m
关联。累加器散列映射的初始状态设置为空({}
)。
您认为这意味着什么?你有什么零件有麻烦? – amalloy
'{} {:b 2:a 1:c 3}' – Srini
@ user1702169将这两幅贴图“粘”在一起这样并不真正有帮助(除非你是代码打高尔夫球)。把它写成“{} {...}”,这将是明确的,那是两件不同的事情。 – cfrick