【问题标题】:Clojure alter update-in returns nil and dosync doesnt allow recurClojure alter update-in 返回 nil 并且 dosync 不允许重复
【发布时间】:2016-10-05 16:10:34
【问题描述】:

编辑:

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

原文:

我试图按如下方式更新 ref 中的哈希图

(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}}]}

但是比我读到的altercalls 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 source 但并没有变得更聪明。 (除此之外,据我了解,alter 实际上并没有调用apply

我希望你们中的一些人会理解这一点,并知道什么是正确的代码。

【问题讨论】:

  • dosync 中使用recur 是什么意思?你真的想要嵌套事务吗?
  • @OlegTheCat 我确实是的,我有一个嵌套的 refs 结构,并且想在路径中找到最后一个,所以我改变它,问题是通过确保有一个函数来解决在 dosync 中调用。
  • @OlegTheCat 顺便说一句,我同意你的问题,如果我会运行交易然后重复发生,那不是一个好主意,因为我认为交易总是一个单一的(在尾部位置)这很好,如果我制作了一个单独的纯函数来搜索路径,也许会更好

标签: clojure hashmap apply stm update-in


【解决方案1】:

问题是sync的签名如下:

(同步标志-暂时忽略和正文)

忽略此宏的第一个参数。文档还建议为它传递nil

transaction-flags => 待定,暂时通过 nil

因此,使用sync 的正确方法是:

> (sync nil (alter example-ref update-in [:some] (partial conj [])))
{:some [{:nested {:structure :foo}}]}

我还建议使用dosync 而不是sync(只是不要弄乱第一个参数;本质上是这些函数are the same):

> (dosync (alter example-ref update-in [:some] (partial conj [])))
{:some [{:nested {:structure :foo}}]}

【讨论】:

  • 其实我之前用过dosync,但是报错了recur被错误数量的args调用,读到dosync是一个匿名函数,你知道怎么解决吗?
  • 您能否编辑您的问题并将导致问题的 MCVE 放入 dosync
猜你喜欢
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多