Hi How could I get the last element of a channel?
channels are queues - you can only get the "last" element by reading everything up to that point
tnx^^ I was thinking much more complex
is there any reasonable way to use this kind of pattern with core.async/map?
(map do-things (repeat constant-val) (range) [actual collection of things])
essentially, I want to provide infinite lazy sequences to my a/map operations, but I'm worried about using onto-chan
with infinite sequences because I don't know if that would mean they never close and will just leak memory
I want a channel that emits values from an infinite sequence that is closed when the a/map
operation completes. essentially, a channel of infinite sequence that terminates when the shortest channel it is grouped with is exhausted
I wouldn't use map
channels, and go blocks are all not very functional things
I would write a go-loop with a counter
(async/go (loop [n 0 coll coll] (if (seq coll) (do (async/>! out (do-things (first coll) n (async/<! in) )) (recur (inc n) (rest coll)) (async/close! out))
or something
seems like that would still stay around if the provided shortest channel was shorter than that counter
what?
in your example you don't actually show any input channel, you just have a bunch of functions from the seq library, so some guess work is required to figure out what you want
that code loops over the values of the coll collection and writes them to out
there is no shorter input channel
the example was using regular map, rather than a/map, I mean to demo the paradigm. let me write out an actual example:
if you are actually operating on channels, async/map does terminate when any of the input channels are closed
right, but the channels that are passed to async/map
when the shortest input channel closes, the async/map closes. yes, but if one of those channels is emitting from an infinite sequence, the fact that the consumer (the async/map
) closes would not mean that the producers also close
right?
it doesn't need to close
it will be blocked because nothing is consuming
if no one is using it, it will be gc'ed
"blocked" in the casual idiom, "parked"
very interesting. what counts as "using" it? this might explain some weird situations where it gets gc'd and I don't want it to be
what?
or, okay, forget the latter sentence. thats mostly just me attempting to explain some behavior that I dont understand that isn't worth going into. I just want to know when a channel is GC'd
same as anything else
right, okay, hahaha
the only difference is go blocks invert things, instead of a go block becoming a thread that is a gc root refering to a channel, a go block becomes a callback that a channel refers to
so if you create a go block that is waiting on a channel C, and don't refer to C anywhere else, they are both gc'able
interesting... so here's an example:
(defn repeat! [val]
(let [out! (chan)]
(go-loop [] (>! out! val) (recur))
out!))
so if I have a reference to the output of repeat!, then that inner go-loop will not close?loops don't close
never?
so it wont be GC'd?
err, I guess it can be GC'd while still being open?
closing is an operation you can do on a channel
a loop is a bit of code that executes
uh huh, and a go-loop is a channel that is executing a loop
no
a go block is not a channel
(with-open [a b] 1)
this with-open returns 1
, is a with-open a number?
yeah, huh. Still mind bendy. a go loop is then... the callback that has state?
yes, it transformed in to a callback and when you do a channel op like >!, <! or alts!, the callback is attached to the channel instead of blocking on the operation
so in your example code, the go-loop is a callback attached to out!, so if you don't have a reference to out!, regardless of open or closed, the whole thing can be gc'ed
huh. Okay, yeah. that makes sense. Well, thanks. Will let this absorb some
really though, thanks for taking the time