如何更好地在Clojure中迭代状态(monad?)

我只写了这段代码:

(defn parameters [transform-factory state]
  (lazy-seq (let [[r1 state] (uniform state)
                  [r2 state] (uniform state)
                  [t state] (transform-factory state)]
              (cons [t [r1 r2]] (parameters transform-factory state)))))

(defn repeated-transform [mosaic n transform-factory state]
  (reduce transform-square mosaic
    (take n (parameters transform-factory state))))

parameters函数会生成一个从state生成的惰性序列值,用于参数化某些事物的重复变换(在本例中为“马赛克”)。

在我看来, parameters显示了一个相当常见的模式,当你有一些必须被携带的state时(在这种情况下产生随机值),这些模式就会出现。 有没有这个名字?

有没有更好的方法来编写第一个函数? 相关问题通常可以通过reduce来解决,这种“携带”状态,但是在这里我没有什么可以减少的。 同样, reductions似乎并不合适。 这是一个monad的好例子吗? (从理论上看,我没有看到你如何定义一种将多个实例组合成一个的方法,但也许这并不会改变实际应用 - 它看起来像monads在其他地方解决的那种问题,某些州需要被带走)。

(ps我提到了随机数字,但是我不能用一个在幕后使用可变状态的解决方案替代这个 - 就像“正常”的随机例程一样 - 这是与问题无关的原因)。


你当然可以看看状态monad,看看它是否适合你。

使用单子的一般指导是:

  • 顺序执行(管道操作)
  • 可重复使用的模块化副作用处理(例如:错误处理/记录/状态)
  • 保持您的业务逻辑清洁纯功能
  • 一些我认为对Clojure非常有用的monad资源是

    Adam Smyczek:Monads简介(视频)http://www.youtube.com/watch?v=ObR3qi4Guys

    和Jim Duey:Monad在Clojure http://www.clojure.net/2012/02/02/Monads-in-Clojure/


    [回答我自己,因为这是我迄今发现的最佳解决方案]

    你可以将上面的内容重写为函数的一个折叠。 所以函数变成数据,状态是“通过”,并且所使用的函数将每个函数依次应用到状态并累积结果。

    我看不到一个优雅的方式来实现这一点 - 被折叠的功能似乎是“新的”,你需要额外的样板来添加/分离状态和累加器 - 所以我用一个称为fold-over的函数包装整个过程。 源代码在这里,正在使用的函数的一个例子就在这里。


    你应该检查的东西是->->> ,线程宏。

    代替这样的代码:

    (let [state (dosomething state)
          state (dosomethingelse state)
          state (dolastthing state)]
        state)
    

    你可以写:

    (-> state (dosomething) (dosomethingelse) (dolasttthing))
    

    其中“线程”通过函数声明,最终返回它。

    现在,您的代码并不完全遵循我所写的内容。 我想它可以遵循的方式是,如果你的功能采取并返回hashmaps。 即(统一状态)可以返回{:state state-val :r1 r1-val}

    然后你可以像这样重写你的代码:

    (->> {:state state} (merge uniform) (merge uniform) (transform-factory))
    

    好多了! :)

    链接地址: http://www.djcxy.com/p/80845.html

    上一篇: How to Better Iterate over State in Clojure (monad?)

    下一篇: Imperative Hybrid