2013-03-11 26 views
2

我有兩個序列用於比較,我需要將比較結果保存在一張地圖中,第一個序列中的數據用作鍵,第二個用作val。這裏說到的是把「相同」的事情上面成一個let綁定之後,但是工作Clojure交換!在綁定中不使用map函數

(def myAtom (atom {})) 

(map #(if (== %1 %2) (swap! myAtom assoc %1 %2)) 
       [1 2 3] [4 5 3]) 

(prn @myAtom) ; ==> {3 3} 

示例代碼,它不工作了

(let [ myAtom (atom {})]  
    (map #(if (== %1 %2) (swap! myAtom assoc %1 %2)) 
       [1 2 3] [4 5 3]) 
    (prn @myAtom)) ;;==> {} empty??? 

所以現在的問題是,會發生什麼myAtom內讓利捆綁?它是如何失蹤?

+2

如果沒有 「其他」 分支你可以用'的when'代替'if'。 – mobyte 2013-03-11 09:01:15

回答

6

map是產生懶惰的序列進行序列的,而你需要的是做序列中每個項目的某些操作(即交換),因此你需要使用doseq

編輯:(更新票面@mobyte建議)

(let [myAtom (atom {}) 
     a [1 2 3] 
     b [4 5 3]]  
    (doseq [[x y] (map vector a b)] 
    (if (== x y) (swap! myAtom assoc x y))) 
    (prn @myAtom)) 

你的第一個例子中的作品,因爲你在執行REPL這使得地圖操作來執行它的懶惰操作每個表達式。

我見過很多人試圖用map來做這樣的某些操作,map只能用於一個目的,即將一個序列映射到另一個序列而沒有任何副作用操作。

4

由於ANKUR提到的,最好使用doseq命令式操作:

(let [myAtom (atom {})]  
    (doseq [[a b] (map vector 
        [1 2 3] 
        [4 5 3])] 
    (when (== a b) (swap! myAtom assoc a b))) 
    (prn @myAtom)) 

但是你可以在你的原始版本使用dorun強制地圖結果的評價:

(let [ myAtom (atom {})]  
    (dorun (map #(when (== %1 %2) (swap! myAtom assoc %1 %2)) 
       [1 2 3] [4 5 3])) 
    (prn @myAtom)) 

附: ANKUR的版本不等同於原來的

doseq

(doseq [a [1 2 3] 
     b [4 5 3]] 
    (println [a b])) 

=> [1 4] 
    [1 5] 
    [1 3] 
    [2 4] 
    [2 5] 
    [2 3] 
    [3 4] 
    [3 5] 
    [3 3] 

map

(dorun (map #(println [%1 %2]) 
      [1 2 3] 
      [4 5 3])) 

=> [1 4] 
    [2 5] 
    [3 3] 
+0

感謝mobyte這是非常有幫助的! – 2013-03-22 06:44:32