如何让有状态Clojure代码纯函数化且避免过度重复?
Clojure(script)纯函数式处理Quad-Edge数据结构的惯用方法
我正在编写一个Clojure库,用于生成Voronoi图,采用某研究论文中描述的quad-edge数据结构。原本我用refs来表示边记录,但出于以下原因,希望将代码改为纯函数式实现:
- 不想让库的使用者操心诸如用
dosync包裹代码这类细节。 - 希望支持非破坏性更新,比如在不修改原始三角剖分的情况下将图裁剪到视口。
refs在Clojurescript中没有实现。
问题在于纯函数式代码需要反复传递数据结构给每个函数,导致代码极度冗余。以下是示例代码:
(defn- bubble-up [qeds cross] (loop [qeds qeds cross cross] (let [l-edge (first-hit qeds cross (q/r-prev qeds cross) q/o-next) r-edge (first-hit qeds cross (q/o-prev qeds cross) q/o-prev) l-valid (above? qeds l-edge cross) r-valid (above? qeds r-edge cross)] (when (or l-valid r-valid) (let [[qeds new-cross] (if (or (not l-valid) (and r-valid (in-circle? (dest qeds l-edge) (org qeds l-edge) (org qeds r-edge) (dest qeds r-edge)))) (connect qeds r-edge (q/sym cross)) (connect qeds (q/sym cross) (q/sym l-edge)))] (recur qeds new-cross))))))
我尝试过多种其他方法,包括:
- 用Java编写可变部分。
- 使用状态monad(稍好一些但仍显笨重且不符合Clojure惯用风格)。
- 将数据结构放入动态变量中。
在Clojure(script)中,有没有标准的、符合惯用风格的方法来处理这类情况?
内容的提问来源于stack exchange,提问作者M. E. Singer
相关产品推荐
相关产品推荐

