2012-09-03 119 views
6

从Clojure开始,我发现了Rich Hickey的演讲,他在一个基本的Ant-Simulator上演示了Clojure的一些优势。Clojure参考项目最新?

此代码是否仍被认为是Clojure的一个很好的参考?特别是当他递归地发送函数给代理来模拟游戏循环时的部分。 例子:

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

编辑:

我不感兴趣的读者#'宏但更羯羊它是地道/ Clojure的好来 递归调用上的代理或不是一个函数。

+0

您可以发布什么特定的代码,以便发布问题,以便我们可以为您提供帮助?否则,我认为这个问题属于程序员。 – octopusgrabbus

+0

为什么递归发送'animation'到'* agent *'时需要'#''reader宏? – noahlz

+2

每次使用时都会评估“动画”。这样'动画'可以随时更改 –

回答

3

这段代码目前在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 

更新

上面是一个人为的例子,实际上不太好,因为有一个各种递归调用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) 

这个故事的寓意是:不使用代理同步计算。将它们用于异步独立任务 - 比如更新显示给用户的动画:)

+0

谢谢@noahz –