Fork me on GitHub
#core-async
<
2018-10-09
>
fmjrey06:10:31

Hi, just stumbling on alt! not working with a local var, and working with a vector literal. Is that expected? If so how do we deal with a dynamic list of channels to read from?

;; with local var
(let [stop-ch (async/chan 1)
      ch1 (async/chan)
      ch2 (async/chan)
      chs [ch1 ch2]]
  (async/go-loop []
    (async/alt!
      chs ([val ch]
           (do
             (println "got" val)
             (recur)))
      stop-ch (println "stopping loop")))
  (async/put! ch1 "one")
  (Thread/sleep 1000)
  (async/put! ch2 "two")
  (Thread/sleep 1000)
  (async/put! stop-ch "stop"))
=> true
stopping loop

;; with vector literal
(let [stop-ch (async/chan 1)
      ch1 (async/chan)
      ch2 (async/chan)
      chs [ch1 ch2]]
  (async/go-loop []
    (async/alt!
      [ch1 ch2] ([val ch]
                 (do
                   (println "got" val)
                   (recur)))
      stop-ch (println "stopping loop")))
  (async/put! ch1 "one")
  (Thread/sleep 1000)
  (async/put! ch2 "two")
  (Thread/sleep 1000)
  (async/put! stop-ch "stop"))
got one
got two
=> true
stopping loop

hiredman16:10:28

use async/alts!

fmjrey19:10:06

Thanks @hiredman for the suggestion, the code below with alts! works:

(let [stop-ch (async/chan 1)
      ch1 (async/chan)
      ch2 (async/chan)
      chs [ch1 ch2]]
  (async/go-loop []
    (let [[val ch] (async/alts! (cons stop-ch chs) :priority true)]
      (if (= stop-ch ch)
        (println "stopping loop")
        (do
         (println "got" val)
         (recur)))))
  (async/put! ch1 "one")
  (Thread/sleep 1000)
  (async/put! ch2 "two")
  (Thread/sleep 1000)
  (async/put! stop-ch "stop"))
got one
got two
=> true
stopping loop

fmjrey19:10:22

It's still odd for alt! to not be consistent, looks like a bug to me

hiredman20:10:14

it has to be that way in order for the macro to be able to determine what to do at macro expand time (vs at runtime)