我使用此函数创建一个新函数,该函数返回一个新位置,用于在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方式?
答案 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
中的处理方式相同。