(defmethod learn [:SARSA :Module] [learner module]
(let [samples (get learner :dataset)]
(for [seq samples]
(let [laststate (atom 0) lastaction (atom 0) lastreward (atom 0)])
;;Do some stuff
;;Update laststate,lastaction,lastreward
)
))
我使用for循环迭代序列,但也许我应该使用常规循环并重复? map / reduce在这里有用吗?
答案 0 :(得分:6)
小心 - 在Clojure中,最好不要将for
视为一个循环,而是作为一个列表理解 - 它需要一个集合并返回该集合的修改/过滤版本
你可以通过使用循环和recur来更加惯用(在更多函数式编程风格中)这样做:
(defmethod learn [:SARSA Module] [learner module]
(loop [samples (get learner :dataset)
last-state 0
last-action 0
last-reward 0]
(if-let [sample (first samples)]
(recur (next samples) (new-last-state) (new-last-action) (new-last-reward))
[last-state last-action last-reward])))
每次使用last-state
,last-action
和last-reward
的新值进行迭代时,(if-let [sample (first samples)]
部分会确定是否还有任何样本需要查看 - 如果没有,这意味着您已经在列表的末尾,而(first '())
将返回nil
,因此您的结果将以您喜欢的任何形式返回 - 看到最后一行,我把它们作为向量返回。如果还有剩余样本,我们会将第一个标记绑定到符号sample
,您可以将其用于last-state
等的更新计算,然后recur
使用这些更新后的值和(next samples)
,这是该列表中第一个样本之后的所有内容。
编辑:我通常会尝试使用map / reduce做任何事情,但是每当你尝试进行复杂的循环操作时,你会计算并计算一些不同的统计数据,loop / recur就是通常是最好的方式。
答案 1 :(得分:5)
@DaveYarwood在答案中提到map
/ reduce
;这是你如何实现它:
(defmethod learn [:SARSA Module] [learner module]
(reduce (fn [[state action reward] sample]
;; do some stuff and computes new values for state/action/reward
[new-state new-action new-reward])
[0 0 0]
(get learner :dataset)))