Clojure - 填充传染媒介的惯用方式,当在圈时

时间:2016-03-23 12:02:27

标签: loops vector clojure

我有一个要求,在收到请求后,我必须从外部源获取值,过滤它们并将过滤后的值返回给调用者。我通过一次从外部源获取指定数量的记录来累积结果(直到达到所需的大小)。我设法提出了一个解决方案,但我不确定它是否是最优雅或惯用的方式。

请参阅下面的模拟代码,其中make-response函数必须将前50个奇数返回给调用者。 (请注意,此代码可能无法处理边缘情况,但我认为它足以用于演示目的)。

也许我应该使用ref代替原子?提前感谢任何建议。

(defn fetch [start]
  (let [end (+ start 10)]
    (range start end)))

(defn take-good-ones [all]
  (filter odd? all))

(defn make-response []
  (let [start (atom 0)
        result (atom [])]
    (while (< (count @result) 50)
      (do
       (let [all-values (fetch @start)
             good-values (take-good-ones all-values)
             handled-this-time (count all-values)]
         (swap! start + handled-this-time)
         (swap! result concat good-values))))
   @result))

2 个答案:

答案 0 :(得分:4)

不需要改变原子或低级循环的东西:

; the next 10 items since start
(defn fetch [start] 
   (range start (+ 10 start)))

; lazy sequence of good values, by getting batches of 10 from `fetch`
(defn all-good-values [] 
   (filter odd? 
      (mapcat #(fetch (* 10 %)) (range))))

(defn make-response [] 
   (take 20 (all-good-values)))

(make-response) => (1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39)

答案 1 :(得分:0)

除了Joost's answer之外,每个批次都被过滤然后连接,因此批处理没有任何效果。所以效果就是

(defn make-response []
  (->> (range) (filter odd?) (take 50)))