Clojure发生器功能

时间:2014-05-28 12:14:08

标签: clojure closures generator

我使用此函数创建一个新函数,该函数返回一个新位置,用于在PDF中放置内容。

生成器必须为每个调用返回新的行位置。但它也必须能够重置为某个值。

(defn pos-generator [initial-val delta] 
    (let [counter (ref initial-val)]
         (fn ([] (dosync (let [cur-val @counter] 
                             (do (alter counter + delta)
                                 cur-val))))
             ([new-val] (dosync (ref-set counter new-val))
                                 ))))


; example usage:
(let [ypos (pos-generator 470 -15)]
     (add-to-pdf "bla bla"    [290 y])
     (add-to-pdf "bla bla"    [290 y]))

但是看起来有点尴尬,是否有更具思想性的Clojure方式?

1 个答案:

答案 0 :(得分:0)

使用atom作为edbond建议使用更多惯用代码IMO,因为您不需要在两个或更多ref之间进行同步,而只需要地点存储不断变化的价值。

(defn pos-generator [initial-val delta] 
  (let [counter (atom initial-val)]
    (fn
      ([]
        (let [cur-val @counter]
          (swap! counter + delta)
          cur-val))
      ([new-val]
        (reset! counter new-val)))))

(let [ypos (pos-generator 470 -15)]
  [[290 (ypos)]
   [290 (ypos)]
   [290 (do (ypos 20) (ypos))]
   [290 (ypos)]])

;= [[290 470] [290 455] [290 20] [290 5]]

作为旁注,我们无需在do表单中的代码中使用let,它的处理方式与do中的处理方式相同。