2017-07-15 74 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關聯。累加器散列映射的初始狀態設置爲空({})。