This snippet is current in Clojure 1.4. Is it idiomatic for a function to submit a task back to the agent that called it? Yes.
Here is an example that uses a similar approach to recursively calculate a factorial:
(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
Update
The above is a contrived example and actually not a good one, as there is a race condition between the various recursive send-off calls and the later await. There may be some send-off calls yet to be added to the agent's task queue.
I re-wrote the above as follows:
(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))
and observed the following behavior:
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)
Moral of the story is: don't use agents for synchronous calculations. Use them for asynchronous independent tasks - like updating animations displayed to a user :)
#'reader macro needed when recursively sendinganimationto*agent*?animationevery time it is used. This wayanimationcan be changed on the fly