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 :)
¿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
¿Por qué es necesaria la macro del lector '# '' cuando se envía de forma recursiva 'animation' a' * agent * '? – noahlz
Esto evalúa 'animación' cada vez que se usa. De esta manera 'animación' puede cambiarse sobre la marcha –