我正在使用代理来操纵一个结构,但我没有副作用。
发送所有信息(我已经打印并计算了它们),但有时候我没有所有的副作用。好像不是我的所有函数都应用于代理的状态,或者最后一次发送是否应用于以前的状态..
我尝试了doall,dorun但没有找到解决方案,感谢任何帮助。
;; aux function for adding an element to a hashmap
(defn extend-regs [reg s o]
(let [os (get reg s)]
(if (nil? os)
(assoc reg s [o])
(assoc reg s (conj os o)))))
;; the agent's altering function - adding an element to the :regs field(a hashmap)
(defn add-reg! [d s o]
(send d (fn [a] (assoc a :regs (extend-regs (:regs a) s o)))))
;; Creating the agents, dct/init returns an agent
;; pds: data for fields
(defn pdcts->init-dcts! [pds]
(doall (map dct/init (map :nam pds) (repeat nil))))
;; Altering one agent's state, dct/add-reg sends an assoc message to the agent
;; d: agent, pd: data for fields
(defn dct->add-regs! [d pd]
(dorun (map (fn [s r] (dct/add-reg! d s r))
(:syms pd)
(:regs pd)))
d)
;; Going through all agents
;; ds: agents, pds: datas
(defn dcts->add-regs! [ds pds]
(dorun (map (fn [d pd] (dct->add-regs! d pd))
ds
pds))
ds)
编辑:============================================= ======
好吧事实证明我还没有等到我的线程来完成他们的任务。现在的问题是如何监控我的代理商。我怎么知道队列中有未完成的线程?我只找到了swank.core / 活动线程和类似的但它们不是解决方案。
答案 0 :(得分:2)
我没有针对您的问题的解决方案,但我无法抗拒建议对前两个功能进行一些改进:
(defn extend-regs [reg s o]
(let [os (get reg s)]
(if (nil? os)
(assoc reg s [o])
(assoc reg s (conj os o)))))
;; => place the 'if inside the assoc:
(defn extend-regs [reg s o]
(let [os (get reg s)]
(assoc reg s (if (nil? os) [o] (conj os o)))))
;; => this (if (nil? x) ...) is the pattern of function fnil, so ...
(defn extend-regs [reg s o]
(let [os (get reg s)]
(assoc reg s ((fnil conj []) os o))))
;; with update-in, this will be even clearer, and we can remove the let altogether:
(defn extend-regs [reg s o]
(update-in reg [s] (fnil conj []) o))
至于第二个:
(defn add-reg! [d s o]
(send d (fn [a] (assoc a :regs (extend-regs (:regs a) s o)))))
;; => We can, again, use update-in instead of assoc:
(defn add-reg! [d s o]
(send d (fn [a] (update-in a [:regs] extend-regs s o))))
;; or, if you can get rid of extend-regs:
(defn add-reg! [d s o]
(send d (fn [a] (update-in a [:regs s] (fnil conj []) o)))
最后,作为一种风格,我会将add-reg放在一个单独的函数中,并直接使用在客户端代码中发送给代理的习惯用法(或者有一个简化的add-reg!函数):
(defn add-reg [v s o] (update-in v [:regs s] (fnil conj []) o))
(defn add-reg! [d s o] (send d add-reg))
我知道这不能回答你的初步问题,但写这个一步一步的重构是很有趣的
答案 1 :(得分:1)
使用await或await-for等待代理人完成当前工作队列:
(await agent1 agent2 agent3)
或
(apply await list-of-agents)
add-reg的一个小改进:
(defn extend-regs [reg s o]
(update-in reg [s] conj o))
这是因为
(conj nil :b) ; => [:b]
因此
(update-in {} [:a] conj :b) ; => {:a [:b]}
最后我们有了。
(defn add-reg! [d s o]
(send d update-in s [:regs] conj o)