1

クロージャを初期状態に復元またはリセットする簡単な方法はありますか?たとえば、以下の関数で、myClosureFnに関連付けられているstat1とstat2の値を1にリセットするにはどうすればよいですか?

この質問のコンテキスト:私はさまざまな関数で以下の構造を使用していますが、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])))

したがって、新しい状態を取得するにmyClosureFnは、クリーンなカウンターを持つ関数を返すを呼び出すだけです。例えば:

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

グローバル状態を持つ代わりに、各関数はそれ自体の状態を持ち歩きます。このような2つの関数を同時に作成して使用することもでき、それらは互いに干渉しません。

于 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を使用している場合は、REPLでmyClosureFnフォームを再評価してください。

于 2013-03-25T10:52:13.297 に答える