在clojure中跟踪先前值的惯用方法是什么?

car*_*ted 3 clojure

(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

      )

    ))
Run Code Online (Sandbox Code Playgroud)

我使用for循环迭代序列,但也许我应该使用常规循环并重复?map/reduce在这里有用吗?

Dav*_*ood 6

要小心 - 在Clojure中,最好for不要将其视为一个循环,而是作为一个列表理解 - 它需要一个集合并返回该集合的修改/过滤版本.

您可以通过使用循环和重复来更加惯用(在更多函数式编程风格中)这样做,如下所示:

(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])))
Run Code Online (Sandbox Code Playgroud)

每次迭代通过与新的价值观last-state,last-action以及last-reward,在(if-let [sample (first samples)]部分确定是否有任何样本留下来看看-如果没有,那就意味着你在列表的末尾,并且(first '())将返回nil,这样你的结果将以您想要的任何形式返回 - 请参阅最后一行,我将它们作为向量返回.如果还有剩下的样本,我们将第一个绑定到符号sample,您可以将其用于更新的计算last-state等,然后recur使用这些更新的值(next samples),这是该列表中第一个样本之后的所有内容.

编辑:我一般会尝试做的事情使用的map/reduce每当我可以,但每当你正在尝试做的,你正在清点并计算不同的统计一小撮复杂的循环操作,循环/易复发通常是最好的方式走.


omi*_*iel 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)))
Run Code Online (Sandbox Code Playgroud)