我有两个序列用于比较,我需要在地图中保留比较结果,第一个序列中的数据用作键,第二个数据用作val。这是一个有效的示例代码
(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里面发生了什么让绑定?怎么会丢失?
答案 0 :(得分:6)
map
是从序列中生成延迟序列,而你需要的是为序列中的每个项做一些操作(即交换),因此你需要使用doseq
编辑:(更新为par @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来做这样的某些操作,map应该仅用于一个目的,即将序列映射到另一个序列而不进行任何副作用操作。
答案 1 :(得分: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))
P.S。 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]