从Clojure开始,我发现了Rich Hickey的演讲,他演示了Clojure在基本Ant模拟器上的一些优势.
这段代码仍然可以被认为是Clojure的一个很好的参考吗?特别是当他递归地向代理发送函数以模拟游戏循环时的部分.例:
(defn animation [x]
(when b/running
(send-off *agent* #'animation))
(. panel (repaint))
(. Thread (sleep defs/animation-sleep-ms))
nil)
Run Code Online (Sandbox Code Playgroud)
编辑:
我对#'阅读器宏不感兴趣,但更不用说它是惯用的/好的Clojure以递归方式调用代理上的函数.
此代码片段当前在 Clojure 1.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
Run Code Online (Sandbox Code Playgroud)
更新
上面是一个人为的例子,实际上并不是一个好的例子,因为各种递归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))
Run Code Online (Sandbox Code Playgroud)
并观察到以下行为:
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)
Run Code Online (Sandbox Code Playgroud)
这个故事的寓意是:不要使用代理进行同步计算。将它们用于异步独立任务 - 例如更新向用户显示的动画:)