Re: core.async timeout channels are values - is this intended
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.kristen...@gmail.com 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 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. -- -- 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.
Re: core.async timeout channels are values - is this intended
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.marc...@gmail.comwrote: 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.kristen...@gmail.com 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 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. -- -- 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. -- -- 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.
Re: core.async timeout channels are values - is this intended
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 cgree...@gmail.com 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.marc...@gmail.com 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.kristen...@gmail.com 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 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. -- -- 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. -- -- 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
Re: core.async timeout channels are values - is this intended
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.marc...@gmail.com 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 cgree...@gmail.com 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.marc...@gmail.com 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.kristen...@gmail.com 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 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. -- -- 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. -- -- 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
Re: core.async timeout channels are values - is this intended
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.comjavascript: 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.comjavascript: 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.comjavascript: 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.comjavascript: 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