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.

Reply via email to