Fork me on GitHub
#core-async
<
2020-05-25
>
jjttjj17:05:14

Is it documented somewhere that the channel returned from a go block is closed after a take, or should this be obvious for a reason I'm missing?

(let [x (go 123)]
  (go
    (println "X" (<! x)) ;;123
    (println "X2" (<! x)) ;;nil
    ))

dpsutton17:05:57

the alternative would be a pending take that parks forever and can never be satisfied?

jjttjj17:05:48

what about a channel you can put something else on later? (I realize this would only be usable if you keep a reference to the result of the go block which isn't how it's meant to be used)

dpsutton17:05:10

but go is not one of those channels?

dpsutton17:05:50

you want to reuse the channel returned from a go block as a general purpose channel and put other things on it?

jjttjj17:05:19

exactly yeah this is what I tried doing

jjttjj17:05:39

I have some api functions that look like this

(defn get-file [this path]
  (go (->entry (<p! (.getFile gentry path gdir/Behavior.CREATE)))))
At first I took a final chan argument to put the result on but then I figured I could get away with just returning the go block

jjttjj17:05:06

then later when just messing with the repl I figured I might be able to re-use that chan instead of having to create one, to put subsequent results on

hiredman17:05:02

Really a go block doesn't return a channel, it returns a readport (a channel is a full duplex combination of a read and write port). A channel just happens to be the most convenient impl of a readport

jjttjj17:05:16

Like basically this is what I was trying

(let [fch (get-file filesystem path)]
  (go-loop []
    (do-stuff-with-file (<! fch))
    (recur)))
using the internal go block to represent the initial value but then reuse it to subsequently "Set" files

jjttjj17:05:41

gotcha thanks, just trying to make sure I understand fully

dpsutton17:05:12

where is the channel returned from the go macro hobbled? it seems that it literally returns (chan 1)

hiredman17:05:46

In the grand tradition of clojure it isn't hobbled

dpsutton17:05:43

sorry. i meant where it loses the write port part 🙂

hiredman17:05:12

core.async has the notion of read and write ports, but always just returns channels

hiredman17:05:35

You just have to imagine that using the writeport part of a channel returned by a go block is undefined behavior

hiredman17:05:51

Similarly for timeouts

hiredman17:05:43

One of the nice things about a concurrent ml style API (over the more traditional csp/go API core.async has) is read/write events are first class things, you can very naturally return a read event even if internally there is a full channel

jjttjj17:05:38

Is it a bad practice to return a go block as sort of an analog to a js/promise, is it better to always explicitly take a channel arg to put the result on?