I have seen many Clojure programmers enthusiastic about the new core.async library and, though it seems very interesting, I am having a hard time seeing how it conforms to Clojure principles, so I have these questions:
Since "go" is a macro (thus modifying code structure) and ensures "<!" is used directly in a go-block, it is not possible to use "<!" inside another function, like this:
(defn take-and-print [c] (println (<! c))) (def ch (chan 1)) (>!! ch 123) (go (take-and-print ch)) Assert failed: <! used not in (go ...) block
It seems to me that this prevents simplicity and composability. Why is it not a problem?
Maybe as a consequence of the previous two issues, a lot of code with core.async uses lower-level constructs such as loop/recur instead of map/filter/reduce. Isn't it a step backwards?
Where am I missing the point?
Thanks in advance.
The first concern - yes the core operations are side effects. However channels don't have the problems normally associated with mutable references as they don't represent a "place" - channels are opaque, you cannot inspect them, in fact you can't even query whether a channel is closed or not beyond reading nil.
The second concern - doing anything more than shallow yield would mean whole program transformation. This is a tradeoff and I think a reasonable one. The level of composition is channels not go blocks and they compose just fine.
The final concern, you can easily do Rx style map/filter/reduce operations over channels and people have already done so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With