2012-09-03 14 views
6

Comenzando con Clojure, descubrí una charla de Rich Hickey donde demuestra algunas de las fortalezas de Clojure en un básico Ant-Simulator.Proyecto de referencia Clojure al día?

¿Se puede considerar este código como una buena referencia para Clojure? Especialmente las partes cuando recursivamente envía funciones a agentes para simular un bucle de juego. Ejemplo:

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

Editar:

No estoy interesado en la macro #' lector, sino más wether es idiomática/buena Clojure a recursiva llamar a una función en un agente o no.

+0

¿Qué código específico recortado puede publicar para que se pueda establecer un problema, para que podamos ayudarlo? De lo contrario, estoy pensando que esta pregunta pertenece a los Programadores. – octopusgrabbus

+0

¿Por qué es necesaria la macro del lector '# '' cuando se envía de forma recursiva 'animation' a' * agent * '? – noahlz

+2

Esto evalúa 'animación' cada vez que se usa. De esta manera 'animación' puede cambiarse sobre la marcha –

Respuesta

3

Este fragmento es actual en Clojure 1.4. ¿Es idiomático que una función envíe una tarea al agente que la llamó? Sí.

Aquí se muestra un ejemplo que utiliza un enfoque similar para calcular de forma recursiva un 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 

actualización

Lo anterior es un ejemplo artificial y en realidad no es una buena idea, ya que hay una condición de carrera entre las diversas llamadas recursivas send-off y la posterior await. Puede haber algunas llamadas send-off que aún deben agregarse a la cola de tareas del agente.

me volvió a escribir lo anterior como sigue:

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

y se observa el siguiente comportamiento:

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) 

Moraleja de la historia es: no utilizar agentes para los cálculos síncronos. Úselos para tareas independientes asíncronas, como actualizar animaciones mostradas a un usuario :)

+0

Gracias @noahz –

Cuestiones relacionadas