What's the idiomatic way to keep track of previous values in 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

      )

    ))

Im using a for loop to iterate through a sequence but perhaps I should use a regular loop and recur? Would a map/reduce be useful here?


Be careful -- in Clojure, it's better to think of for not as a loop, but as a list comprehension -- it takes a collection and returns a modified/filtered version of that collection.

You can do this more idiomatically (in a more functional programming style) by using loop and recur, something like this:

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

Each time you iterate through with new values for last-state , last-action and last-reward , the (if-let [sample (first samples)] part determines whether there are any samples left to look at -- if there aren't, that means you're at the end of the list, and (first '()) will return nil , so your results will be returned in whatever form you'd like -- see the last line, where I just returned them as a vector. If there are still samples left, we bind the first one to the symbol sample , which you can use for your updated calculations of last-state , etc., then recur with these updated values and (next samples) , which is everything after the first sample in that list.

EDIT: I would generally try and do things using map/reduce whenever I can, but whenever you are trying to do a complicated looping operation where you're tallying and calculating a handful of different statistics, loop/recur is usually the best way to go.


@DaveYarwood alluded to map / reduce in his answer ; here's how you could implement it:

(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)))
链接地址: http://www.djcxy.com/p/66882.html

上一篇: 在clojure中处理状态是否有一种惯用的方式?

下一篇: 在clojure中追踪以前的价值的惯用方法是什么?