Hi Brian, I had the same requirement while building an application, it included a GUI and I wanted to perform some actions only after the user was done editing some text. I also first implemented a solution using an atom, Thread/sleep and a future. It didn't seem right though, since I was creating a bunch of threads all the time, so I tried an approach with the tools core.async provides and the result was the following:
(defn timeout-channel "Creates a channel and a go block that takes from it. The go block keeps an internal status with two possible values, `:wait` and `:receive`. In ':wait' status, execution is blocked until there's a value available in the channel, it then enters the ':receive' status, until the timeout wins. Returns the channel where events need to be pushed." [timeout-ms f] (let [c (async/chan)] (async/go-loop [status :wait args nil] (condp = status :wait (recur :receive (async/<! c)) :receive (let [[_ ch] (async/alts! [c (async/timeout timeout-ms)])] (if (= ch c) (recur :receive args) (do (async/thread (if (sequential? args) (apply f args) (f args))) (recur :wait nil)))))) c)) Signalling the go block to terminate when the event source is no longer available is missing, but that simple enough to implement. Maybe this is something you can use as a starter point. Hope it helps, Juan On Monday, December 1, 2014 6:37:56 PM UTC-3, 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 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.