如何更好地在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