6

Clojureから始めて、Rich Hickeyによる、基本的なAnt-SimulatorでのClojureの長所のいくつかを示す講演を発見しました。

このコードは、Clojureの優れたリファレンスと見なすことができますか?特に、ゲームループをシミュレートするために、彼がエージェントに関数を再帰的に送信するときの部分。例:

(defn animation [x]
  (when b/running
    (send-off *agent* #'animation))
    (. panel (repaint))
  (. Thread (sleep defs/animation-sleep-ms))
  nil)

編集:

私は#'リーダーマクロには興味がありませんが、エージェントの関数を再帰的に呼び出すことが慣用的で優れたClojureであるかどうかは関係ありません。

4

1 に答える 1

3

このスニペットはClojure1.4で最新のものです。関数がそれを呼び出したエージェントにタスクを送信するのは慣用的ですか?はい。

同様のアプローチを使用して階乗を再帰的に計算する例を次に示します。

(defn fac [n limit total]
  (if (< n limit)
    (let [next-n (inc n)]
       (send-off *agent* fac limit (* total next-n)) 
       next-n)
     total))

 (def a (agent 1))

 (await (send-off a fac 5 1))
 ; => nil
 @a
 ;=> 120

アップデート

上記は不自然な例であり、実際には良い例ではありません。さまざまな再帰send-off呼び出しとそれ以降の呼び出しの間に競合状態があるためawaitです。send-offエージェントのタスクキューにまだ追加されていないコールがいくつかある可能性があります。

上記を次のように書き直しました。

(defn factorial-using-agent-recursive [x]
  (let [a (agent 1)]
    (letfn [(calc  [n limit total]
               (if (< n limit)
                 (let [next-n (inc n)]
                   (send-off *agent* calc limit (* total next-n))
                   next-n)
                 total))]
      (await (send-off a calc x 1)))
    @a))

そして、次の動作を観察しました。

user=> (for [x (range 10)] (factorial-using-agent-recursive 5))
(2 4 3 120 2 120 120 120 120 2)
user=> (for [x (range 10)] (factorial-using-agent-recursive 5))
(2 2 2 3 2 2 3 2 120 2)
user=> (for [x (range 10)] (factorial-using-agent-recursive 5))
(120 120 120 120 120 120 120 120 120 120)

話の教訓は次のとおりです。同期計算にエージェントを使用しないでください。ユーザーに表示されるアニメーションの更新など、非同期の独立したタスクに使用します:)

于 2012-09-03T18:01:23.143 に答える