【问题标题】:Clojure idiomatic get-and-set functionClojure 惯用的 get-and-set 函数
【发布时间】:2012-05-22 21:51:16
【问题描述】:

有没有比在 Clojure 中编写 get-and-set 函数更惯用/可读的方式:

(def the-ref (ref {}))

(defn get-and-set [new-value]
  (dosync
    (let [old-value @the-ref]
     (do
       (ref-set the-ref new-value)
       old-value))))

【问题讨论】:

    标签: clojure


    【解决方案1】:

    对于简单的情况,我倾向于直接使用此操作而不是包装在函数中:

    hello.core> (dosync (some-work @the-ref) (ref-set the-ref 5))
    5
    

    在这种情况下,dosync 通常用作您正在寻找的包装器。在dosync 中这很重要,因为dosync 可以很好地与其他事务组合并使事务的边界可见。如果您处于包装函数可以完全封装对 ref 的所有引用的位置,那么 refs 可能不是最好的工具。

    refs 的典型用法看起来更像是这样的:

    (dosync (some-work @the-ref @the-other-ref) (ref-set the-ref @the-other-ref))
    

    很少需要包装它,因为当使用 ref 时,它们通常以多个 ref 为一组使用,因为手头的问题需要协调更改。在它们只是一个值的情况下,原子更常见。

    【讨论】:

    • get-and-set 的原因是我想对当前在 ref 上的值进行批处理。 ref 实际上是 refs 的映射,多个线程同时更新。由于批处理涉及到一些io,所以我认为我需要在事务之外进行,所以我需要获取ref的当前值并以原子方式重置它。
    • ref 中的任何事务都将成为一个大事务的一部分,因为 dosyncs 吸收了内部事务。在 refs 中产生副作用和阻塞操作的官方方法是将它们从 ref 发送给代理。 Refs 保证只发送一次,并且只发送实际提交给结果的结果。如果事务中止,则不发送消息。
    • 原子或代理可能会让你的生活更轻松地解决这个问题。
    • Arthur,将批次发送给代理确实是一个非常非常好的主意。非常感谢!
    猜你喜欢
    • 2016-03-17
    • 2010-12-08
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    相关资源
    最近更新 更多