2017-05-13 48 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拋出原始異常。)