不确定这里发生了什么,但是我有这个代码,map函数在我的repl中成功执行而不包含在已定义的函数中:
(def dogs '({:name "scout" :age 5} {:name "rux" :age 3} {:name "fenley" :age 2}))
(def ages (atom {:above-four '() :below-four '()}))
(map
#(if (> (get-in % [:age]) 4)
(swap! ages update-in [:above-four] merge %)
(swap! ages update-in [:below-four] merge %)) dogs)
@ages
=> {:above-four ({:name "scout", :age 5}), :below-four ({:name "fenley", :age 2} {:name "rux", :age 3})}
然而,当我定义地图功能时:
(def ages (atom {:above-four '() :below-four '()}))
(def dogs '({:name "scout" :age 5} {:name "rux" :age 3} {:name "fenley" :age 2}))
(defn test-dogs []
(map
#(if (> (get-in % [:age]) 4)
(swap! ages update-in [:above-four] merge %)
(swap! ages update-in [:below-four] merge %)) dogs)
@ages)
我得到以下结果:
=> {:above-four (), :below-four ()}
我很困惑,因为直接从Clojure文档中获取的这个函数效果很好:
(def m1 (atom {:a "A" :b "B"}))
(defn update-m1 []
(swap! m1 assoc :a "Aaay")
@m1)
=> {:a "Aaay", :b "B"}
答案 0 :(得分:5)
由于test-dogs
使用map
,因此会返回延迟序列。懒惰序列的元素直到它们需要才被实现。
您设置的问题是您尝试使用map
来运行副作用(对swap!
的调用;不纯的操作),并且从不实际使用结果map
。因为您从未向map
请求结果,所以包含swap!
的映射函数永远不会运行。
使用mapv
(返回非惰性向量)或doseq
(用于执行副作用):
(doseq [dog dogs]
(let [k (if (> (:age dog) 4)
:above-four
:below-four)]
(swap! ages update k merge dog)))
您可以强制运行副作用。
我清理了一下代码。您使用的-in
版本是不必要的;就像对get-in
的呼唤一样。我也摆脱了对swap!
的多余调用。
请注意,至少在您的示例中,使用atom
s是完全没必要的。即使您有一个更复杂的用例,请确保它们的使用是合理的。可变变量在Clojure等语言中并不常见。