2017-05-13 47 views
1

我正在使用agents来设置处理链。我也想让记录器记录发生的事情。整个代码都在这里。记录Clojure代理

我可以看到:charlie MSG被处理并作为它在打印甚至进到log功能... 后被“已发送”是“conj'ed”到记录器代理。

为什么查理从来没有出现在我的@logger

(def logger (agent [])) ;; logger to keep track of what's done 

(defn log [msg] 
    (send logger conj msg) ;; charlie's msg is NOT conj'ed 
    (println "logged" msg)) ;; but charilies msg IS printed 

(defn create-relay [coll] 
    (reduce (comp agent vector) nil (reverse coll))) ;; see partial answer below 

(defn relay-msg [next-agent prev-msg] 
    (if (nil? next-agent) 
    (log "finished relay") 
    (let [new-msg (str prev-msg (second next-agent))] 
     ;; do something interesting with new-msg then: 
     (log new-msg) 
     ;; go do the next thing 
     (send (first next-agent) relay-msg new-msg)))) 

(send (create-relay [:alice :bob :charlie]) relay-msg "hello") 
(. java.lang.Thread sleep 5000) 
(prn @logger) 

输出:

logged hello:alice 
logged hello:alice:bob 
logged hello:alice:bob:charlie 
["hello:alice" "hello:alice:bob"] 
;; expected last line to be: 
;; ["hello:alice" "hello:alice:bob" "hello:alice:bob:charlie"] 

部分答案 我已经找到如何使它工作,但我仍然在寻找“接受”,解释的答案在错误去掩盖从我。

印刷是一个副作用。代理是“一致的”状态(无论这意味着什么)。后“日志”查理,下一行调用这一行“发送到无”:

(send (first next-agent) relay-msg new-msg) ;; =>(first next-agent) is nil 

看起来这应该是一个NullPointerException但它永远不会显示出来。吞下,因为它在另一个线程?

固定以下难以神交变化:

(reduce (comp agent vector) nil (reverse coll)) 
;; => change to => 
(reduce (comp agent vector) (agent nil) (reverse coll)) 

为什么在错误沉默? @logging回滚了吗?
如果在回滚之后还有其他项与“logging”结合了什么呢?

我有“工作”的代码,但我仍然失去了正确的行为。 “联合国”记录的东西听起来很可怕。

回答

2

答案上可以找到的Clojure reference page for Agents

  • 如果功能执行过程中的任何其他调度是由(直接或间接),它们将被保持,直到后代理的状态已经改变。
  • “其他急件” 在这里是指,在本质上,调用send。因此,当针对特定代理执行relay-msg时,所有对send的调用都将排队,直到relay-msg返回代理的新状态。在:alice:bob的情况下,一旦代理的状态被更新,排队的send就被分派。

    但由于relay-msg:charlie抛出一个NullPointerException,用于:charlie所述药剂投入错误状态和排队send S(包括一个在调用log)被丢弃。

    看起来像它应该是一个NullPointerException但它永远不会出现。吞下,因为它在另一个线程?

    的排序。实际上,异常是由代理调度机制封装的。如果传递给send的函数引发异常,它将被捕获并且代理处于错误状态。例外情况存储在代理上,可通过agent-error访问。 (此外,对失败代理的后续调用send抛出原始异常。)