Fork me on GitHub
#core-async
<
2021-06-11
>
Daniel Craig21:06:14

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?

hiredman21:06:37

yes, alt with a timeout

hiredman21:06:59

the buffer function above is an example of that

Daniel Craig21:06:47

Ok great that’s just what I needed

Daniel Craig21:06:00

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?

jjttjj22:06:20

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

jjttjj22:06:18

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)