1

有什么快速的方法可以将闭包恢复或重置为其初始状态?例如,在下面的函数中,如何将与 myClosureFn 关联的 stat1 和 stat2 的值重置为 1?

这个问题的背景:我在不同的函数中使用下面的结构,一个函数可能会“弄乱”与闭包相关的值。因此,我需要将其重置/恢复为初始状态,以便再次将其传递给另一个函数。

(def myClosureFn 
  (let [stat1 (atom 1)
        stat2 (atom 1)
        ;..stat3 stat4 ...
        ]
    (fn [m]
      (swap! stat1 inc)
      (reset!   stat2 (* 2 m))
      [@stat1  @stat2])))

(myClosureFn 1) ;--> [2 2] 
(myClosureFn 2) ;--> [3 4]
(myClosureFn 2) ;--> [4 4]
(myClosureFn 3) ;--> [5 6]
;...
; how to get [ 1 1 ] back to myClosureFn ?
4

2 回答 2

3

与其明确地重新设置与您的函数关联的状态,不如考虑使用高阶函数:

(defn myClosureFn []
  (let [stat1 (atom 1)
        stat2 (atom 1)
        ;..stat3 stat4 ...
        ]
    (fn [m]
      (swap! stat1 inc)
      (reset!   stat2 (* 2 m))
      [@stat1  @stat2])))

所以,要获得新鲜的状态,你只需调用myClosureFnwhich 返回一个带有干净计数器的函数。例如:

> (def f1 (myClosureFn))
> (def f2 (myClosureFn))
> (f1 1) ;--> [2 2]
> (f1 2) ;--> [3 4]
> (f2 1) ;--> [2 2]
> (f1 3) ;--> [4 6]

每个函数都带有自己的状态,而不是全局状态。您甚至可以同时创建和使用两个这样的功能,它们不会相互干扰。

于 2013-03-25T15:40:21.087 回答
2

当没有传递参数时,您可以使其myClosureFn像重置函数一样

(def myClosureFn 
  (let [stat1 (atom 1)
        stat2 (atom 1)
        ;..stat3 stat4 ...
        ]
    (fn [& [m]]
      (if m
        (do
          (swap! stat1 inc)
          (reset!   stat2 (* 2 m))
          [@stat1  @stat2])
        (do
          (reset! stat1 1)
          (reset! stat2 1))))))


(myClosureFn 1) ;--> [2 2] 
(myClosureFn 2) ;--> [3 4]
(myClosureFn) ;reset to 1 1

或者,如果您使用的是 REPL,那么只需myClosureFn在 REPL 中重新评估表单。

于 2013-03-25T10:52:13.297 回答