【问题标题】:Creating refs with transducers使用传感器创建参考
【发布时间】:2015-03-11 18:44:52
【问题描述】:

是否可以在 Clojure 中使用转换器创建 ref,其方式类似于使用转换器创建 chan

即,当您使用传感器创建 chan 时,它会将所有输入过滤/映射到输出中。

我希望还有一种方法可以创建ref,这样无论您设置什么,它都可以忽略或修改输入。这可以吗?

【问题讨论】:

    标签: clojure transducer


    【解决方案1】:

    向通道添加一个转换器会在内容通过时对其进行修改,这大致类似于向 ref 添加一个 watch,每次值更改时都会应用它自己的更改。这个改变它自己然后再次触发手表,所以如果它们是递归的,请注意不要破坏堆栈。

    user> (def r (ref 0))
    #'user/r
    user> (add-watch r :label
                     (fn [label the-ref old-state new-state]
                       (println "adding that little something extra")
                       (if (< old-state 10) (dosync (commute the-ref inc)))))
    #<Ref@1af618c2: 0>
    user> (dosync (alter r inc))
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    adding that little something extra
    1
    user> @r
    11
    

    如果你愿意,你甚至可以对原子的状态应用一个转换器。

    【讨论】:

      【解决方案2】:

      这是一个有趣的想法,但至少有几个原因是错误的做法。你会失去一些你希望保持的关系:

      (alter r identity) =/= r
      
      (alter r f)(alter r f) =/= (alter r (comp f f))
      
      (alter r f) =/= (ref-set r (f @r))
      

      此外,一些传感器是具有副作用的挥发物,在 dosync 块中没有任何业务。即,如果您使用 (take n) 作为您的传感器,那么如果您的 dosync 失败,那么它将像使用 (take (dec n)) 调用一样重试,这违反了 dosync 主体要求。

      问题在于ref 允许您将读写操作作为单独的步骤进行。相反,如果有一些基础功能可以让您将输入“应用”到隐藏的“状态”并在一个步骤中收集所有输出,并且与 STM 一致,那么这将是可以使用的东西。

      【讨论】:

        猜你喜欢
        • 2011-06-24
        • 1970-01-01
        • 2021-07-18
        • 1970-01-01
        • 2021-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多