Fork me on GitHub
#core-async
<
2016-09-29
>
josh.freckleton23:09:32

I'm just learning async, and I expect the following to print "hi", why does it not, and return a channel only?

noisesmith23:09:03

go returns a channel no matter what, and reading and writing the same channel in a go block is not supported

noisesmith23:09:07

I don't understand that question (or does it refer to an example you haven't shared yet?)

noisesmith23:09:57

never mind, I fail at slack UI

josh.freckleton23:09:19

the second example has putting and taking in one go block...

noisesmith23:09:04

right, I think the buffer either fixes the read/write in one block issue, or works accidentally and the read/write is not officially supported - I'll see if I can find out which

josh.freckleton23:09:35

ah, thanks for your help, and I'm ok if you don't figure it out, sounds like a lot of work 😉

josh.freckleton23:09:18

I'm going between haskell, clojure, and python right now, and noticing a lot of interesting patterns in each about their little quirks, haha

josh.freckleton23:09:30

(esp in how they compare to each other)

noisesmith23:09:37

oh! - I think I know what it is. >! does not return until the data is consumed

noisesmith23:09:59

so in the first example, it parks, and the consume that would follow can't run

noisesmith23:09:04

the buffer prevents that behavior

noisesmith23:09:35

so I should say, >! only returns if there is room in the channel's buffer, which means that if there is no buffer, it doesn't return until the message is consumed

noisesmith23:09:52

which is impossible in the original example

josh.freckleton23:09:11

doesn't >! return immediately always?

josh.freckleton23:09:44

(`>!!` blocks, no?)

noisesmith23:09:26

no, >! parks

noisesmith23:09:47

so it blocks the rest of the code in that go block (but it doesn't block the thread - the thread works on other go blocks if available)

noisesmith23:09:05

, >!! blocks the thread itself

josh.freckleton23:09:12

if I don't declare a buffer size, how big is it? I assumed infinite...

josh.freckleton23:09:22

ah. k, this could explain some of my confusion...

josh.freckleton23:09:46

but how about this example, how can a buffer size of 0 accomplish anything?

(let [c (chan)]
  (go (while true (println (<! c))))
  (for [_ (range 10)] (go (>! c (rand-int 1000)))))

josh.freckleton23:09:08

I mean, the previous prints 10 random digits... why would that work with a buffer of 0?

noisesmith23:09:09

because >! only parks the go block it is inside

noisesmith23:09:23

you don't need any buffering for any of that to work

noisesmith23:09:12

that won't work if you don't consume the return value of the let, by the way, because for is lazy. The normal thing would be to use doseq instead of for there

noisesmith23:09:39

the Print step of the REPL consumes it, so it accidentally works, but only when doing it interactively

noisesmith23:09:00

josh.freckleton: parking is telling core.async that the go block you are in can be ignored until your operation is ready to complete

josh.freckleton23:09:04

ah, that's why I can't swap the 2 lines in my latter example, but I can if I use doseq... gotcha.

noisesmith23:09:39

also, (dotimes [_ 10] ...) is identical to (doseq [_ (range 10)] ...) except it's more efficient because it doesn't need to create a lazy-seq

noisesmith23:09:51

(the efficiency is minor, but dotimes is still nicer)

josh.freckleton23:09:27

ah, thanks! ya, doseq wan't part of my repertoire since most of my code to-date has been pure (side-effect-free), at least I try to. But now that I'm getting into async, gotta flip my mind back to imperative.

josh.freckleton23:09:49

(PS wow, async makes trivial some complex ideas that i've tried to build ad-hoc in other languages)