Thanks for the response and discussion. Your proposal solves the problem, but not the general observation: that timeout channels are not usable keys. A small tweak on your proposal can make a key-safe channel:
(defn unique-timeout [ms] (let [c (chan)] (take! (timeout ms) (fn [_] (close! c))) c)) (do (loop [ch->v (into {} (for [v [1 2 3]] [(unique-timeout 1000) v]))] (when-let [chs (keys ch->v)] (let [[_ ch] (alts!! chs)] (println (ch->v ch)) (recur (dissoc ch->v ch))))) (println "done")) I think the lesson learned is, that the implementation of timeout-channels favours efficiency over the possibility of storing them in maps or sets, and removing them from these datastructures in a loop. Once again, thanks for all the feedback! Thomas On Wednesday, November 20, 2013 10:53:45 AM UTC, Michał Marczyk wrote: > > As for scheduling the printlns, this prints out 1, 2, 3 (in some order): > > (let [c (chan)] > (doseq [v [1 2 3]] > (take! (async/timeout 1000) (fn [_] (put! c v)))) > (go-loop [v (<! c)] > (println v) > (recur (<! c)))) > > Cheers, > Michał > > > On 20 November 2013 11:34, Michał Marczyk <michal....@gmail.com<javascript:>> > wrote: > > The behaviour of timeout channels is to close after the timeout > > elapses. This will be visible everywhere the channel is used. > > > > Cheers, > > Michał > > > > > > On 20 November 2013 11:22, Cedric Greevey <cgre...@gmail.com<javascript:>> > wrote: > >> Isn't that not only violating least astonishment, but potentially > >> introducing a terrible bug into the library? One could use "two > different" > >> timeout channels in two different alts, and if the timeout channels are > >> aliased, then perhaps only one of the alts would actually get notified. > >> > >> > >> On Wed, Nov 20, 2013 at 5:05 AM, Michał Marczyk > >> <michal....@gmail.com<javascript:>> > > >> wrote: > >>> > >>> The reason = considers you timeout channels to be equal is that they > >>> are, in fact, the same object. In fact, they may end up being the same > >>> object even with different timeout values: > >>> > >>> (identical? (timeout 1) (timeout 2)) > >>> ;= true > >>> > >>> Except I got a false just now with a fresh REPL and same timeout > >>> value... All subsequent invocations return true though, and I'm sure > >>> with a little digging the reason for the false would become clear. > >>> > >>> The reason for them being the same object is that timeout goes out of > >>> its way to avoid creating to many timeout channels and will reuse > >>> existing ones if their timeouts are due within a small amount of time > >>> (clojure.core.async.impl.timers/TIMEOUT_RESOLUTION_MS, currently 10 > >>> ms) of the requested timeout. > >>> > >>> Cheers, > >>> Michał > >>> > >>> On 20 November 2013 10:08, Thomas G. Kristensen > >>> <thomas.g....@gmail.com <javascript:>> wrote: > >>> > Hi all, > >>> > > >>> > I ran into a core.async behaviour that confused me a bit the other > day. > >>> > In > >>> > some of our systems, we need to fire different timeouts, perform > actions > >>> > and > >>> > schedule a new timeout. The problem is, that if the timeouts are of > the > >>> > same > >>> > number of ms, we can't distinguish them, and therefore not keep > track of > >>> > and > >>> > remove them from a set (at least not easily). > >>> > > >>> > That sounds a bit fuzzy. Hopefully this spike will make it clearer > what > >>> > I'm > >>> > trying to say: > >>> > > >>> > (require '[clojure.core.async :refer [chan timeout alts!! alts!]]) > >>> > > >>> > (= (chan) (chan)) > >>> > ;; false > >>> > > >>> > (= (timeout 1) (timeout 2)) > >>> > ;; false > >>> > > >>> > (= (timeout 1) (timeout 1)) > >>> > ;; true > >>> > > >>> > (do (loop [ch->v (into {} (for [v [1 2 3]] [(timeout 1000) v]))] > >>> > (when-let [chs (keys ch->v)] > >>> > (let [[_ ch] (alts!! chs)] > >>> > (println (ch->v ch)) > >>> > (recur (dissoc ch->v ch))))) > >>> > (println "done")) > >>> > ;; only fires "3", the last channel in the map > >>> > > >>> > The intended behaviour of the last loop is to print 1, 2 and 3 (not > >>> > necessarily in that order). However, the ch->v map will only contain > one > >>> > key, as timeouts with the same duration are considered the same > value. > >>> > In > >>> > the real example, a new timeout with the same value should be > scheduled > >>> > again, by being put in the map. > >>> > > >>> > So, my questions are: > >>> > > >>> > - Is this intended behaviour? > >>> > - Is there a different pattern for achieving the scheduling > behaviour > >>> > I'm > >>> > looking for? > >>> > > >>> > Thanks for your help, > >>> > > >>> > Thomas > >>> > > >>> > -- > >>> > -- > >>> > 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/groups/opt_out. > >>> > >>> -- > >>> -- > >>> 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/groups/opt_out. > >> > >> > >> -- > >> -- > >> 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/groups/opt_out. > -- -- 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/groups/opt_out.