2013-03-11 27 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