从Clojure向量原子中删除第一项并返回它
我有一个原子包裹着一个项目向量:从Clojure向量原子中删除第一项并返回它,clojure,Clojure,我有一个原子包裹着一个项目向量: (def items (atom [1 2 3 4])) 我想自动删除第一项并将其返回。此代码说明了逻辑: (let [x (first @items)] (swap! items #(subvec % 1)) x) 但是当许多线程相互竞争时,上面的代码是不正确的。读取和更新之间存在竞争条件 如中所述,原子用于不协调的同步访问。我希望这可以用原子而不是ref来实现,因为原子更简单 是否有一种只使用原子而不使用参考物的解决方案?(我将尝试使用手表,看看
(def items (atom [1 2 3 4]))
我想自动删除第一项并将其返回。此代码说明了逻辑:
(let [x (first @items)]
(swap! items #(subvec % 1))
x)
但是当许多线程相互竞争时,上面的代码是不正确的。读取和更新之间存在竞争条件
如中所述,原子用于不协调的同步访问。我希望这可以用原子而不是ref来实现,因为原子更简单
是否有一种只使用原子而不使用参考物的解决方案?(我将尝试使用手表,看看效果如何。)如果您的答案坚持需要ref,请您解释一下为什么需要ref,即使在需要“协调同步访问多个身份”时建议使用ref(与上面的链接相同)
这与其他相关问题不同,例如和,因为我想更新向量原子并返回值。带有
比较数据集的自旋循环用于交换代码>一个原子。Clojure还提供较低级别的比较和设置代码>用于原子,您可以使用它进行自己的自旋循环,并返回旧值和新值
(defn swap*!
"Like swap! but returns a vector of [old-value new-value]"
[atom f & args]
(loop []
(let [ov @atom
nv (apply f ov args)]
(if (compare-and-set! atom ov nv)
[ov nv]
(recur)))))
(defn remove-first-and-return [atom]
(let [[ov nv] (swap*! atom subvec 1)]
(first ov)))
如果需要使用atom,请使用本地封装的atom来存储获胜事务的in-transaction值的第一个元素
(let [f-atom (atom nil)]
(swap! items-atom #(do (reset! f-atom (first %))
(rest %)))
@f-atom)
或者,使用ref
和dosync
事务块实现相同的功能:
(dosync
(let [f (first @items-ref)]
(alter items-ref rest)
f)))
这里,如果事务因并行写入操作成功而失败,则事务不会返回,也不会对ref产生影响,直到可以重试,以便读写操作不会被另一个写入操作中断。这不是此用例的解决方案,但对其他人来说可能是这样
您可以在atom上创建一个手表,它将发送一个包含新旧值的事件。我的解决方案是在包含值的元数据中存储所需的任何返回值。我不知道这有多惯用,它显然只适用于实现IMeta
接口的类
(defn pop-head!
[a]
(-> (swap! a #(with-meta (subvec % 1) {:head (% 0)}))
(meta)
:head))
这得益于交换返回原子现在存储的值。让我们试试看:
(def a (atom [1 2 3 4]))
(pop-head! a) ;; => 1
(pop-head! a) ;; => 2
(pop-head! a) ;; => 3
(pop-head! a) ;; => 4
(pop-head! a) ;; => IndexOutOfBoundsException...
是的,你可能想处理那个案子 自从添加了交换VAL
在Clojure 1.9中,您可以使用(ffirst(swap vals!items rest))
从向量返回第一个元素,并在单个操作中更新原子。我认为执行此操作所需的长度表明这超出了原子的预期用途。:)“但是,很好的破解。”我也这么认为——直到我看到它也依赖于。compareAndSet
的循环。我现在认为这是对原子的一种很好的利用。为什么要为这个简单的用例设置一个ref呢?看起来Prismatic已经有一段时间了,使用了更好的交换对代码>in。对于这种不使用另一个atom存储in事务值的方法,到Prismatic Pimping的交换对的链接当前为+1。也许一个有名称空间的kw会使解决方案更加通用。为了记录在案,在Clojure Google小组中有一个类似的讨论,这可能是一个有趣的问题。好问题!!!!!!你添加了标签…但你的问题与此有关吗?(Web提要格式)