【问题标题】:clojure - refactor from atom into immutableclojure - 从原子重构为不可变
【发布时间】:2015-08-15 06:15:06
【问题描述】:

我有一个嵌套的 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)
                         (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 的情况下实现相同的行为?

【问题讨论】:

    标签: clojure


    【解决方案1】:
    ;; 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))
    

    【讨论】:

    • [(inc counter') t']中的单引号是什么意思
    • counter't' 是绑定名称,遵循命名的数学约定,例如。 xx'x'' 等,其中' 表示序列中的“下一个值”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    相关资源
    最近更新 更多