문제

I wrote this helper function:

(defn iterate-converge
  "Returns the value from calling (f x) some number of times, until
  `x` changes by less than a tolerance, `tol`. Will not execute more
  than `b` (e.g. bailout) times."
  [f x0 tol b]
  (loop [f f x x0 tol tol b b i 0]
    (if (>= i b)
      (throw (ex-info "Failed to converge"
                      {:type ::failed-to-converge :tol tol :b b}))
      (let [x' (f x)]
        (if (< (abs (- x x')) tol)
          x'
          (recur f x' tol b (inc i)))))))

Depending upon the parameters, this can take a significant amount of time. I'd like the function report on its progress. I don't want it to be tied to console output (e.g. println).

My current ideas:

  1. Add a callback function as a parameter. Call it for each pass through. This allows for push notification.
  2. Add an atom as a parameter. Update it for each pass through. This would allow for polling or push notification by using add-watch.
  3. Add a core.async channel as a parameter. Similar to (1) above but may give better multicore performance.

What would you do and why?

도움이 되었습니까?

해결책

Just make it return a lazy sequence of candidate answers. Then you can iterate through them at your leisure, stopping whenever the answer is acceptable, or when you decide it's taken too long and you want to give up.

다른 팁

Personally I would rank these options in reverse order, #3 being most flexible because then you can handle the output in more interesting (and fun) ways.

If you are looking for more options, I can recommend the Narrator library as a way to accurately produce periodic reports of long running processes.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top