This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-15
Channels
- # adventofcode (110)
- # announcements (30)
- # aws (2)
- # babashka (39)
- # babashka-sci-dev (112)
- # beginners (155)
- # calva (5)
- # cider (12)
- # clj-kondo (11)
- # cljs-dev (1)
- # cljsrn (2)
- # clojure (144)
- # clojure-australia (2)
- # clojure-europe (14)
- # clojure-nl (5)
- # clojure-spec (3)
- # clojure-uk (2)
- # clojurescript (22)
- # core-async (23)
- # cursive (31)
- # data-science (3)
- # emacs (12)
- # events (1)
- # fulcro (8)
- # honeysql (7)
- # jobs-discuss (11)
- # lsp (1)
- # missionary (28)
- # nextjournal (7)
- # off-topic (64)
- # pedestal (3)
- # polylith (19)
- # reagent (14)
- # reitit (12)
- # releases (4)
- # shadow-cljs (33)
- # tools-deps (3)
- # xtdb (3)
Given the code below, expected to see the my repl to output the "1" instead nothing happened. Can someone explain why. I created two channels, the go loop created a running loop where the value should be taken from in-ch and put on out-ch if odd, then the take! should take from out-ch and call println on the value in the callback.
(def in-ch (chan))
(def out-ch (chan))
(go-loop []
(let [val (<! in-ch)]
(when (odd? val)
(>! out-ch val)))
(recur))
(put! in-ch 1)
(take! out-ch println)
works for me:
% clj -A:async
Clojure 1.10.3
user=> (require '[clojure.core.async :refer [chan <! >! put! take! go-loop]])
nil
user=> (def in-ch (chan))
#'user/in-ch
user=> user=> (def out-ch (chan))
#'user/out-ch
user=>
user=> (go-loop []
(let [val (<! in-ch)]
(when (odd? val)
(>! out-ch val)))
(recur))
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x605c2b9f "clojure.core.async.impl.channels.ManyToManyChannel@605c2b9f"]
user=>
dan@mbp-m1 async % clj -A:async
Clojure 1.10.3
user=> (require '[clojure.core.async :refer [chan <! >! put! take! go-loop]])
nil
user=> (def in-ch (chan))
#'user/in-ch
user=> (def out-ch (chan))
#'user/out-ch
user=> (go-loop []
(let [val (<! in-ch)]
(when (odd? val)
(>! out-ch val)))
(recur))
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x1adc38a0 "clojure.core.async.impl.channels.ManyToManyChannel@1adc38a0"]
user=> (put! in-ch 1)
true
user=> (take! out-ch println)
1
nil
user=>
does it matter that i'm in cljs?
err it is working
emacs did a thing with my repl that is confusing to me. The value are above my user> and cljs.user> prompt!
I had to scroll up
ignore the "val: 1" outputs, i added that print statment
anyway, thanks.
no problem. this is an nrepl problem i think. nrepl works great for expressions returning values. It’s not so great for arbitrary printing that happens asynchronously
is there a better way to track things?
asynchronous events i suppose. I was just surprised by the behavior and it lead me to believe people weren't doing this, when most tutorials i see on async do involve repl output. But maybe there is some sort of way to check the system that isn't staring at the docs. I suppose specs, graphs, etc could be used.
treating (atom [])
as a log of events, with (swap! a conj x)
replacing (println x)
is a start
println for async debugging has multiple problems, but most repls don't move the prompt around obscuring the timing like emacs does
Given the following code (same as above + 3 lines marked with X) i expected my repl to just ouput 9 because i closed the go-loop channel. Instead i get the
9
11
(def in-ch (chan))
(def out-ch (chan))
(def looper
(go-loop []
(let [val (<! in-ch)]
(when (odd? val)
(>! out-ch val)))
(recur)))
(put! in-ch 9)
(take! out-ch println)
X (close! looper)
X (put! in-ch 11)
X (take! out-ch println)
Did i not close the channel, or does putting a value on a chan re-open it? How do modify a running go-block at run time or is that not possible? How do you do it in repl development at least.close! looper closes the output channel of the go-loop, it doesn't stop the loop
usually, you want to put an if at the beginning of your go-loop that will stop when receiving nil (protip: if-some
is useful here) and then you can close the in-ch to stop the loop
like this?
(def looper
(go-loop []
(if-some [val (<! in-ch)]
(do
(>! out-ch val)
(recur))
(close! in-ch))))
i believe Alex means that if you close the in-ch elsewhere, then your if-some will be false and your go-loop will stop on its own. you shouldn’t close in-ch from looper
(def looper
(go-loop []
(if-some [val (<! in-ch)]
(do
(>! out-ch val)
(recur))
(println "in-ch has closed, looper exiting"))))
;; separately
(put! in-ch 9)
(close! in-ch) ;; causes looper to stop
yes, that
awesome, yep that makes sense to me.
brb. thanks for the help 🙂