用于进度报告的惯用语?

Ale*_*ard 33 lisp functional-programming clojure imperative-programming

我应该如何监控clojure中映射函数的进度?

当用命令语言处理记录时,我经常每隔一段时间打印一条消息,以指示事情已经走了多远,例如报告每1000条记录.基本上这是计算循环重复.

我想知道在clojure中我可以采取什么方法,我将一个函数映射到我的记录序列.在这种情况下,打印消息(甚至保持进度计数)似乎基本上是副作用.

到目前为止我想出的是:

(defn report
  [report-every val cnt]
  (if (= 0 (mod cnt report-every))
    (println "Done" cnt))
    val)

(defn report-progress
  [report-every aseq]
  (map (fn [val cnt] 
          (report report-every val cnt)) 
       aseq 
       (iterate inc 1)))
Run Code Online (Sandbox Code Playgroud)

例如:

user> (doall (report-progress 2 (range 10)))
Done 2
Done 4
Done 6
Done 8
Done 10
(0 1 2 3 4 5 6 7 8 9)
Run Code Online (Sandbox Code Playgroud)

是否有其他(更好)的方法来实现这种效果?

我在做什么有任何陷阱?(我认为我保留了懒惰,而不是举个例子.)

Art*_*ldt 32

关于clojure的好处是你可以将报告附加到数据本身而不是执行计算的代码.这允许您分离这些逻辑上不同的部分.这是我的misc.clj中的一个块,我发现我几乎在每个项目中使用:

(defn seq-counter 
  "calls callback after every n'th entry in sequence is evaluated. 
  Optionally takes another callback to call once the seq is fully evaluated."
  ([sequence n callback]
     (map #(do (if (= (rem %1 n) 0) (callback)) %2) (iterate inc 1) sequence))
  ([sequence n callback finished-callback]
     (drop-last (lazy-cat (seq-counter sequence n callback) 
                  (lazy-seq (cons (finished-callback) ())))))) 
Run Code Online (Sandbox Code Playgroud)

然后将报告器包裹在您的数据周围,然后将结果传递给处理函数.

(map process-data (seq-counter inc-progress input))
Run Code Online (Sandbox Code Playgroud)

  • 我将上述解决方案中的概念概括为一个库,以便可以轻松地将其放入项目中。希望这对某人有帮助。[https://github.com/tmountain/seq-peek](https://github.com/tmountain/seq-peek)。 (2认同)

小智 6

我可能会在代理商中执行报告.像这样的东西:

(defn report [a]
  (println "Done " s)
  (+ 1 s))

(let [reports (agent 0)]
  (map #(do (send reports report)
            (process-data %))
       data-to-process)
Run Code Online (Sandbox Code Playgroud)