编辑:
dosync自己创建了一个函数,因此对recur的调用被解释为对生成的函数dosync的调用。
这是我实际创建的函数的足迹。尽量简单点,我想。
(defn change-to-ref [ref data]
(dosync
(if-let [[new-ref new-data] (some-test @ref data)]
(recur new-ref new-data)
(alter ref f data))))例外情况:
CompilerException java.lang.IllegalArgumentException:
Mismatched argument count to recur, expected: 0 args, got: 2原件:
我试图在参考文件中更新一个hashmap,如下所示
(def example-ref (ref {:some {:nested {:structure}}}))
(defn f [this] [this]) ;; just an example function
(sync (alter example-ref update-in [:some] f)
user=> nil这很令人惊讶,因为它应该会回来
user=> {:some [{:nested {:structure}}]}所以比我试过:
(update-in @example-ref [:some] f)
user=> {:some [{:nested {:structure}}]}但我所读到的alter是这样称呼apply的:
(apply update-in @example-ref '([:some] f))
user=> {:some nil}好吧,那么让我们用正确的方式:
(apply update-in @example-ref (list [:some] f))
user=> {:some [{:nested {:structure}}]}很好,我弄明白了,但这并不能解释为什么alter出了问题,我甚至不能改变它.
(apply (fn [a b] (update-in a b f)) @example-ref '([:something]))
user=> {:some [{:nested {:structure}}]}它看起来很糟糕,但至少它能工作,我可以为alter :D模拟它。
(sync (alter example-ref (fn [a b] (update-in a b f)) [:some])
user=> nil好吧,你赢了。
我看了一眼:clojure.lang.Ref.alter源,但一点也不聪明。(除此之外,据我所知,alter实际上并没有调用apply)
我希望你们中的一些人能理解这一点,并对什么是正确的代码有一个答案。
发布于 2016-10-05 16:24:00
问题是sync的签名如下:
(同步标志-忽略了“现在”和“身体”)
忽略此宏的第一个参数。此外,文档还建议传递nil:
事务标记=> TBD,暂时传递零。
因此,使用sync的正确方法是:
> (sync nil (alter example-ref update-in [:some] (partial conj [])))
{:some [{:nested {:structure :foo}}]}我还建议使用dosync而不是sync (只是不要弄乱第一个参数;本质上是这些函数都是一样的):
> (dosync (alter example-ref update-in [:some] (partial conj [])))
{:some [{:nested {:structure :foo}}]}https://stackoverflow.com/questions/39878987
复制相似问题