问题
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