Clojure、Agent、无副作用

标签 clojure agent

我正在使用代理来操纵结构,但我并没有产生所有副作用。

所有消息都已发送(我已打印并计算了它们),但有时我没有收到所有副作用。好像并非我的所有功能都应用于代理的状态,或者最后一次发送应用于先前的状态..

我尝试了 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/active-threads 和类似的,但它们不是解决方案。

最佳答案

我没有解决您问题的方法,但我忍不住建议对前两个功能进行一些改进:

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

我知道这并不能回答你最初的问题,但是编写这个逐步重构很有趣

关于Clojure、Agent、无副作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6649819/

相关文章:

tensorflow - tf-agent 的 `policy` 和 `collect_policy` 有什么区别?

internet-explorer - IE 11 - F12 开发工具 - 如何为 IE session 自动设置 "user agent string"

machine-learning - 强化学习 - 代理如何知道选择哪个 Action ?

javascript - 使用简单反射代理的流行 'vaccumCleaner' 玩具问题解决方案

Clojure 应用程序未在 Heroku 上启动; Aleph + RedisToGo 超时

clojure - 与 Clojure 的序列不一致?

clojure - 为什么使用 onyx 的棱柱模式验证失败(ExceptionInfo 值与模式不匹配)?

clojure - 为什么我在没有显式递归的函数上收到 StackoverflowError

c++ - 如何在 Clojure 中创建 C 风格的结构体?

sql-server - SQL Server 代理在 SQL Server 2014 Express 中不工作