clojure-从atom重构为不可变
我有一个嵌套的reduce函数,我使用一个名为counter的原子在每次满足条件时递增一个计数clojure-从atom重构为不可变,clojure,Clojure,我有一个嵌套的reduce函数,我使用一个名为counter的原子在每次满足条件时递增一个计数 (defrecord TreeNode [val left right]) (defn build-tree [node xs] (let [counter (atom 1)] (reduce (fn [t x] (reduce (fn [t l] (if-not (= (:val l) -1)
(defrecord TreeNode [val left right])
(defn build-tree [node xs]
(let [counter (atom 1)]
(reduce (fn [t x]
(reduce (fn [t l]
(if-not (= (:val l) -1)
(let [next-branch (nth xs @counter)]
(swap! counter inc)
;; do stuff
) t)
)t (map-indexed
(fn [idx itm]
(let [side (if (= 0 idx) :left :right)]
{:side side :index idx :val itm})) x))) node xs)))
我不喜欢在函数中使用可变的ref。有没有一种方法可以在不使用ref的情况下实现相同的行为?单引号在[(inc counter')t']
counter'
中是什么意思,t'
是绑定名称,遵循命名的数学约定,例如x
,x'
等。其中
表示“下一个值”依次
;; for starters, we can pass the counter through each reduce
(defn build-tree [node xs]
(let [[counter tree] (reduce (fn [[counter tree] x]
(reduce (fn [[counter' t] l]
(if-not (= (:val l) -1)
(let [next-branch (nth xs counter)
... ...
t' ...]
[(inc counter') t'])
[counter' t])
[counter t]
(map-indexed
(fn [idx itm]
(let [side (if (= 0 idx) :left :right)]
{:side side :index idx :val itm}))
x))))
[0 node]
xs)]))
;; the code becomes much clearer with apropriate let bindings
(defn build-tree
[node xs]
;; the optional name arg to an anonymous function makes stack traces much easier to read
(let [process-branch (fn process-branch [[counter t] l]
(if-not (= (:val l) -1)
(let [next-branch (nth xs counter)
... ...
t' ...]
[(inc counter) t'])
[counter t]))
mark-branch (fn mark-branch [x]
(map-indexed
(fn [idx itm]
(let [side (if (= 0 idx) :left :right)]
{:side side :index idx :val itm}))
x))
[counter tree] (reduce (fn [[counter tree] x]
(reduce process-branch
[counter t]
(mark-branch x)))
[0 node]
xs)]
tree))