Fork me on GitHub

Can anyone explain what would be the advantage of using take! recursively over a go-loop? Example:

;; avoid using go-loops with aot here
(take! err-ch (fn loop-fn [e]
                (error-fn e)
                (take! err-ch loop-fn)))
The comment on avoiding go-loops with aot is in the original source. Copied from


take! has a callback as its second arg


the callback invokes it again


so it's a sort of trampoline - every time the take succeeds, it invokes a new take


the advantage is that go blocks compile by doing a transform on their body, I wouldn't be surprised if that interacts poorly with aot with certain core.async versions


I don't know of the specific bug (and my alternative would be just never doing aot...)


I'd like to do a pipe and apply a transducer to the values taken from from before putting them to to. pipeline seems to do exactly this. However, I've usually thought of the pipeline* functions in core.async as utilities for doing things in parallel. Is it typical to use pipeline with a parallelism of 1 for this sort of task?


Is there a good reference for how to reliably log to a repl window from a go-loop? I’m using timbre from a mount-managed go-loop and I almost certainly don’t have it hooked up right. I’ve resorted to resetting an atom from within the loop and have an add-watch set up outside the loop.


(the more general teach-me-to-fish-ish question: understanding what exactly is going on with stdout, etc. and the various places it might hide).


on the java level, stdout is attached by default to System/out


in clojure, the dynamic var *out* is derived by default from Sytem/out


but the value of *out* can be modifed, via dynamic binding or just plan redefinition / resetting


many loggers intentionally don't use out- try askin our logger to print to *out* instead of its current method?


but on the other hand, it might be more elegant to have a go loop that reads a channel and logs every entry it consumes (instead of the logger library handling this ordering via queue for you)


oh, thanks. Ok. I’ll try passing *out*. I’m still learning what’s what with core.async and I’m finding it challenging when I can’t see things happen in a log stream.


Is this the kind of thing I should be doing with (tap> ,,,)?


I haven't played with tap - but it would be one way to do this(?)


Ok, I’ll see if that helps too. Now to log *out* and see what it is in various places with wild abandon.


@rgm If you're doing this for debugging purposes, I'd reach for tap> first. Then either use Cognitect's REBL or use a second REPL connected into the first one and add a tap listener that just println's the tapped data.


(I've used that second approach quite often to get a simple console logging stream running outside my main REPL/editor setup)


by second repl do you mean in an editor, or say connecting a second nrepl via lein connect? (I’m in a lein project)


The latter. Just from another terminal window so you can add-tap to get println output in that second REPL.


(that way the tap values are printed just to the stdout of that second REPL)


Hmm, I just tried that and it doesn't actually work the way I expected with Leiningen... I'm used to doing it with a Socket REPL and it works there. I wonder what Leiningen is doing differently with stdout?


yeah, between lein and fireplace (vim user) it’s not really clear to me where it’s all being swallowed


(I haven't used Leiningen for anything for years at this point)


that second repl’s a neat trick though, thanks.


is the idea that tap> calls can just stay in place and they don’t matter if no taps are attached?


Yup. They'll just tap into the void if nothing is listening. They have a dropping channel buffer behind them I believe. Maybe 1024 entries?