スレッドが最も簡単な解決策になりそうですが、スレッド1つで自分で管理することはあまり難しくありません。あなたに100msしか与えない "シミュレーション"環境では、新しいスレッドを許可しないことが多いので、これは別の方法です。
基本的な考え方は、タスクを終了するために実行する必要がある作業を表すクロージャを作成し、終了する時間がない場合は結果の代わりにその作業を戻すことです。ここにスケッチがあります:それは一連の数字を追加し、100msごとではなく10回の操作ごとに中断されます。
(let [timer (atom 9)]
(defn keep-going? []
(not= 0 (swap! timer #(mod (inc %) 10)))))
(defn saving-addition [sum xs]
(if-let [[x & more] (seq xs)]
(let [next-thunk (fn [] (saving-addition (+ x sum) more))]
(if (keep-going?)
(next-thunk)
next-thunk))
sum))
(defn monitor [xs]
(loop [thunk (saving-addition 0 xs)]
(if (fn? thunk)
(do
(println "Saving execution state")
(recur (thunk)))
thunk)))
user> (monitor (range 25))
Saving execution state
Saving execution state
Saving execution state
300
編集:Clojureにはテールコールの最適化がないため、サンクを作成してからスタックを使用します。割り込みが必要となる前に、数千ステップ以上を実行する可能性がある場合は、スタックオーバーフローが発生します。唯一の現実的な解決策は、あなたが複数のそのような「懸濁」関数を記述しなければならない場合、マクロでアウトこの抽象おそらく可能性
(defn saving-addition [sum xs]
(if-let [[x & more] (seq xs)]
(let [sum (+ x sum)]
(if (keep-going?)
(recur sum more)
#(saving-addition sum more)))
sum))
のように、recur
の両方にと継続中サンクのボディを複製することです。行うには
ツリーはソートされていませんか?あなたがそれを得るなら、あなたはいくつかの要素を見つけて真を返す必要があるか、あるいは道を必要とするだけですか? – toto2