は、ここで私はどうなるのかです:
(require '[clojure.core.async :as a])
(defn interval [f msecs]
(let [timing (a/chan)
kickoff
#(a/go
(a/<! (a/timeout msecs))
(a/>! timing true))]
(a/go-loop []
(when (a/<! timing)
(a/go (f))
(kickoff)
(recur)))
(kickoff)
#(a/close! timing)))
例:
(let [i (interval #(prn "tick") 2000)]
(Thread/sleep 7000)
(i))
;; "tick"
;; "tick"
;; "tick"
;;=> nil
この方法で、すべてのあなたの状態はローカルであり、むしろグローバルアトムを使用するよりも、ブロックをチャネルを介して処理して行くれます。ループの各繰り返しで行われる作業はほぼ一定であるため、実際のインターバル時間は、渡したmsecs
の数にかなり近くなるはずです。への別の呼び出しを保証する場合は、年代順に実行し、あなたの代わりにこのような何かを行うことができます:ここでは
(。この関数の使用法は私の以前のinterval
機能と同じである)
(require '[clojure.core.async :as a])
(defn interval [f msecs]
(let [action (a/chan (a/dropping-buffer 1))
timing (a/chan)
kickoff
#(a/go
(a/<! (a/timeout msecs))
(a/>! timing true))]
(a/go-loop []
(when (a/<! action)
(f)
(recur)))
(a/go-loop []
(if (a/<! timing)
(do
(a/>! action true)
(kickoff)
(recur))
(a/close! action)))
(kickoff)
#(a/close! timing)))
をf
に対するすべての呼び出しはしています同じループ。私は、f
への呼び出しがmsecs
よりも長くかかる場合、今後の呼び出しが遅れていくのを開始するかもしれないので、バッファリングを使用しています。ここで