core-async

2019-03-28T21:08:12.001400Z

Hi How could I get the last element of a channel?

alexmiller 2019-03-28T21:13:56.001900Z

channels are queues - you can only get the "last" element by reading everything up to that point

2019-03-28T21:18:37.002700Z

tnx^^ I was thinking much more complex

idiomancy 2019-03-28T22:07:39.006100Z

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

idiomancy 2019-03-28T22:08:44.007400Z

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

2019-03-28T22:11:16.007700Z

I wouldn't use map

2019-03-28T22:11:43.008100Z

channels, and go blocks are all not very functional things

2019-03-28T22:11:58.008500Z

I would write a go-loop with a counter

2019-03-28T22:14:56.010600Z

(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

idiomancy 2019-03-28T22:17:40.011100Z

seems like that would still stay around if the provided shortest channel was shorter than that counter

2019-03-28T22:23:42.011400Z

what?

2019-03-28T22:24:46.012300Z

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

2019-03-28T22:25:01.012900Z

that code loops over the values of the coll collection and writes them to out

2019-03-28T22:25:07.013200Z

there is no shorter input channel

idiomancy 2019-03-28T22:25:25.013600Z

the example was using regular map, rather than a/map, I mean to demo the paradigm. let me write out an actual example:

2019-03-28T22:26:07.014600Z

if you are actually operating on channels, async/map does terminate when any of the input channels are closed

idiomancy 2019-03-28T22:26:26.015100Z

right, but the channels that are passed to async/map

idiomancy 2019-03-28T22:27:20.016300Z

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

idiomancy 2019-03-28T22:27:22.016500Z

right?

2019-03-28T22:29:25.016700Z

it doesn't need to close

2019-03-28T22:29:42.017200Z

it will be blocked because nothing is consuming

alexmiller 2019-03-28T22:29:43.017300Z

if no one is using it, it will be gc'ed

2019-03-28T22:30:17.018400Z

"blocked" in the casual idiom, "parked"

idiomancy 2019-03-28T22:30:55.019100Z

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

2019-03-28T22:32:22.019500Z

what?

idiomancy 2019-03-28T22:33:21.020500Z

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

2019-03-28T22:33:39.020800Z

same as anything else

idiomancy 2019-03-28T22:34:21.022Z

right, okay, hahaha

2019-03-28T22:34:47.022800Z

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

2019-03-28T22:35:39.023700Z

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

idiomancy 2019-03-28T22:36:27.024500Z

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?

2019-03-28T22:36:45.024800Z

loops don't close

idiomancy 2019-03-28T22:37:32.025100Z

never?

idiomancy 2019-03-28T22:37:42.025400Z

so it wont be GC'd?

idiomancy 2019-03-28T22:38:05.025900Z

err, I guess it can be GC'd while still being open?

2019-03-28T22:38:16.026200Z

closing is an operation you can do on a channel

2019-03-28T22:38:27.026600Z

a loop is a bit of code that executes

idiomancy 2019-03-28T22:38:45.026900Z

uh huh, and a go-loop is a channel that is executing a loop

2019-03-28T22:38:50.027200Z

no

2019-03-28T22:39:04.027600Z

a go block is not a channel

2019-03-28T22:40:50.029700Z

(with-open [a b] 1) this with-open returns 1, is a with-open a number?

idiomancy 2019-03-28T22:41:12.030Z

yeah, huh. Still mind bendy. a go loop is then... the callback that has state?

2019-03-28T22:42:09.031500Z

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

2019-03-28T22:42:56.032400Z

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

idiomancy 2019-03-28T22:44:52.033200Z

huh. Okay, yeah. that makes sense. Well, thanks. Will let this absorb some

idiomancy 2019-03-28T22:45:02.033500Z

really though, thanks for taking the time