How do I iterate until a fixed point in Clojure?

徘徊边缘 提交于 2019-12-11 02:33:23

问题


I'm frequently in the position that my code reads like so:

(iterate improve x)

And I'm looking for the first value that no longer is an improvement over the previous. Neither filter nor take-while lend themselves to an obvious solution. However, I'm hesitant to write out:

(loop [current x
       next (improve x)]
  (if (= current next)
    current
    (recur next (improve next))))

or:

(let [improvements (iterate improve x)]
  (->> (map vector improvements (rest improvements))
    (filter (partial apply =))
    (ffirst)))

Because at some point this is becoming repetitive and surely fixed point iteration is such a basic task that there must be some kind of library support somewhere, right?


回答1:


You can use reduce and reduced to stop when necessary. reduced wraps the argument in a special object, which reduce is designed to look for and stop processing immediately returning the wrapped value.

(def vals (iterate improve x))

(reduce #(if (= %1 %2) (reduced %1) %2) vals)



回答2:


You could use drop-while then first:

(defn still-improving? [[x y]]
  ...)

(->> st
     (iterate transition)
     (partition 2 1)
     (drop-while still-improving?)
     ffirst)


来源:https://stackoverflow.com/questions/44478322/how-do-i-iterate-until-a-fixed-point-in-clojure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!