core-async

2021-06-11T21:24:14.022500Z

Hi, this may be related to the above discussion, but is there an idiomatic way of taking from a channel in batches with a timeout?

2021-06-11T21:24:37.022800Z

yes, alt with a timeout

2021-06-11T21:24:59.023100Z

the buffer function above is an example of that

2021-06-11T21:28:47.023600Z

Ok great that’s just what I needed

2021-06-11T21:53:00.024500Z

Ok, pardon the question, but when I try that buffer function in my REPL I get ‘Can only recur from tail position’. What am I overlooking?

2021-06-11T22:56:20.024700Z

I think you should be able to just remove that last recur statement, and put those values in the loop bindings instead

2021-06-11T22:57:18.024900Z

ie

(defn buffer
  [in ms N]
  (let [out (chan)]
    (go
      (loop [b [(<! in)] timer (timeout ms)]
        (if timer
          (alt!
            timer (do (>! out b)
                      (recur [] nil))
            in ([v]
                (let [new-buffer (conj b v)]
                  (if (= N (count new-buffer))
                    (do
                      (>! out new-buffer)
                      (recur [] nil))
                    (recur new-buffer timer))))))))
    out))
(can't test it out at the moment)