woops should actually be (go-loop [] (let [[v c] (alts! [(timeout period) events-ch])] (if (= c events-ch) (when v (recur)) (apply f args))))
the timeout returns nil.... On Wednesday, December 3, 2014 3:47:35 PM UTC-5, Erik Price wrote: > > Thank you for calling my attention to this possibility! > > e > > On Wed, Dec 3, 2014 at 2:49 PM, Dylan Butman <dbu...@gmail.com > <javascript:>> wrote: > >> Erik that's pretty! But be careful about go-loops and closed channels. >> This will recur infinitely if events-ch is closed (it will continuously >> return nil) >> >> (defn invoke-after-uninterrupted-delay >> >> ([period events-ch f] >> >> (invoke-after-uninterrupted-delay period events-ch f [])) >> >> ([period events-ch f & args] >> >> (async/go-loop [] >> >> (let [[v p] (async/alts! [(async/timeout period) events-ch])] >> >> (when v >> >> (if (= p events-ch) >> >> (recur) >> >> (apply f args))))))) >> will allow the go-loop to return when the channel is closed. >> >> >> On Monday, December 1, 2014 8:33:10 PM UTC-5, Erik Price wrote: >>> >>> Coincidentally, we recently wrote code to do something very similar. The >>> following function will invoke f after period milliseconds, unless a >>> value is sent on events-ch, in which case the timeout is reset (and >>> starts counting down again): >>> >>> (defn invoke-after-uninterrupted-delay >>> ([period events-ch f] >>> (invoke-after-uninterrupted-delay period events-ch f [])) >>> ([period events-ch f & args] >>> (async/go-loop [] >>> (let [[_ p] (async/alts! [(async/timeout period) events-ch])] >>> (if (= p events-ch) >>> (recur) >>> (apply f args)))))) >>> >>> e >>> >>> >>> On Mon, Dec 1, 2014 at 6:50 PM, Brian Craft <craft...@gmail.com> wrote: >>> >>>> That version has the unfortunate behavior that (func) can be >>>> interrupted if (event) is called while it is running. Here's another >>>> version using an agent: >>>> >>>> (defn queue-with-delay2 [period func] >>>> (let [q (agent nil)] >>>> (fn [] >>>> (send-off q (fn [t] >>>> (when t >>>> (future-cancel t)) >>>> (future (Thread/sleep period) (send-off q (fn [_] >>>> (func) nil)))))))) >>>> >>>> Running with a sleep to see that (func) is not canceled by subsequence >>>> (event) calls: >>>> >>>> (def event (queue-with-delay2 2000 #(do (println "running") >>>> (Thread/sleep 2000) (println "ending")))) >>>> >>>> Oddly, if calling (event) between "running" and "ending" messages, the >>>> repl will stack-overflow on the return value. No idea what that's about. >>>> But, running like this is fine: >>>> >>>> (do (event) nil) >>>> >>>> >>>> >>>> >>>> >>>> On Monday, December 1, 2014 1:37:56 PM UTC-8, Brian Craft wrote: >>>>> >>>>> I have need to perform an action when a series of events is quiet for >>>>> some period. That is, if one event arrives an action is queued to execute >>>>> after some timeout. If a second event arrives the timeout is reset, and >>>>> so-forth. >>>>> >>>>> The following code seems to work, however I'm wondering if calling >>>>> 'future' from 'swap!' is a bad idea (side effecting), and if there's a >>>>> better way. >>>>> >>>>> (defn queue-with-delay [period func] >>>>> (let [f (atom nil)] >>>>> (fn [] >>>>> (when @f >>>>> (future-cancel @f)) >>>>> (swap! f (fn [_] (future (Thread/sleep period) (func))))))) >>>>> >>>>> >>>>> Use like >>>>> >>>>> (def event (queue-with-delay 2000 #(println "running"))) >>>>> (event) >>>>> (event) >>>>> (event) ; pause 2 sec >>>>> "running" >>>>> >>>>> >>>>> >>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Clojure" group. >>>> To post to this group, send email to clo...@googlegroups.com >>>> Note that posts from new members are moderated - please be patient with >>>> your first post. >>>> To unsubscribe from this group, send email to >>>> clojure+u...@googlegroups.com >>>> For more options, visit this group at >>>> http://groups.google.com/group/clojure?hl=en >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "Clojure" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to clojure+u...@googlegroups.com. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.