[英]Clojure Atom Doesn't Update When Wrapped in Defined Function
Not sure what is going on here, but I have this code, where the map function successfully executes in my repl without being wrapped in a defined function: 不知道这里发生了什么,但是我有这段代码,其中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})}
Yet, when I define the map function as such: 但是,当我这样定义map函数时:
(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)
I get the following result: 我得到以下结果:
=> {:above-four (), :below-four ()}
I'm very confused, because this function taken straight from the Clojure docs works just fine: 我很困惑,因为直接从Clojure文档中获取的此功能可以正常工作:
(def m1 (atom {:a "A" :b "B"}))
(defn update-m1 []
(swap! m1 assoc :a "Aaay")
@m1)
=> {:a "Aaay", :b "B"}
Because test-dogs
uses map
, it returns a lazy sequence . 由于
test-dogs
使用map
,因此它返回一个惰性序列 。 The elements of lazy sequences aren't realized until they're needed. 直到需要时才意识到惰性序列的元素。
The problem with your set up is you're trying to use map
to run a side effect (the call to swap!
; an impure action), and never actually use the result of map
. 设置的问题是,您试图使用
map
产生副作用(调用swap!
;不纯净的动作),而从不实际使用map
的结果。 Because you never request results from map
, the mapping function containing swap!
因为您永远不会从
map
请求结果,所以包含swap!
的映射函数swap!
never runs. 永远不会运行。
By using mapv
(which returns a non-lazy vector), or doseq
(which is meant to carry out side effects): 通过使用
mapv
(返回一个非惰性向量)或doseq
(它会产生副作用):
(doseq [dog dogs]
(let [k (if (> (:age dog) 4)
:above-four
:below-four)]
(swap! ages update k merge dog)))
You can force the side effects to run. 您可以强制副作用运行。
I cleaned up the code a bit. 我整理了一下代码。 The
-in
versions you were using were unnecessary; 您使用的
-in
版本是不必要的; as was the the call to get-in
. 就像
get-in
的调用一样。 I also got rid of the redundant calls to swap!
我也摆脱了多余的
swap!
电话swap!
. 。
Note though that at least in your example, use of atom
s is entirely unnecessary. 请注意,尽管至少在您的示例中,完全不需要使用
atom
。 Even if you have a more complicated use case, make sure their use is justified. 即使您有更复杂的用例,也请确保合理使用它们。 Mutable variables just aren't as common in languages like Clojure.
可变变量在Clojure之类的语言中并不常见。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.