2012-09-03 155 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 –