2012-09-03 13 views
6

Zaczynając od Clojure, odkryłem rozmowę Rich Hickey, w której demonstruje niektóre mocne strony Clojure'a na podstawowym Ant-Simulator.Projekt Clojure Projekt na bieżąco?

Czy ten kod nadal może być uważany za dobre odniesienie dla Clojure? Zwłaszcza części, gdy rekurencyjnie wysyła funkcje agentom, aby symulować pętlę gry. Przykład:

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

Edit:

Nie jestem zainteresowany w makro #' czytnika ale pogoda jest idiomatyczne/dobrze Clojure do rekursywnie wywołać funkcję na środek czy nie.

+0

Jaki konkretny kod został snipped możesz opublikować, aby można było podać problem, abyśmy mogli Ci pomóc? W przeciwnym razie myślę, że to pytanie należy do programistów. – octopusgrabbus

+0

Dlaczego potrzebne jest makro czytnika '# '' podczas rekursywnego wysyłania 'animation' do' * agenta * '? – noahlz

+2

Wylicza "animację" za każdym razem, gdy jest używana. W ten sposób 'animacja' może być zmieniana w locie –

Odpowiedz

3

Ten fragment jest aktualny w Clojure 1.4. Czy funkcja, aby przekazać zadanie agentowi, który go nazwał, jest idiomatyczny? Tak.

Oto przykład, który wykorzystuje podejście podobne do rekurencyjnie obliczyć silnię:

(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 

Aktualizacja

Powyższe jest wymyślony przykład i rzeczywiście nie jest dobre, ponieważ istnieje stan wyścigu między różnymi wywołaniami rekurencyjnymi send-off i późniejszym . Może być jeszcze kilka połączeń send-off do dodania do kolejki zadań agenta.

I ponownie napisałem wyżej, co następuje:

(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)) 

i zaobserwować następujące zachowanie:

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) 

Morał z tej historii jest taki: Nie używaj środków do synchronicznych obliczeń. Używaj ich do asynchronicznych zadań niezależnych - takich jak aktualizowanie animacji wyświetlanych użytkownikowi :)

+0

Dziękuję @noahz –