Each program consists of two parts: one part, which always contains non-talk data, spits out, etc. For this part, we know what core.async has, but the .async kernel has mutable things, but pay attention to two things. The state of the channels is mainly controlled by the library. What you give is what flowstate can be called. This means that when you put something like a channel, you do not expect to return to it or even change it.
Core.async is a pleasure to manage this part of your program. Otherwise, all the transformations and calculations of your data clojure try to give you good tools to do this functionally.
It seems to me that this prevents simplicity and convenience. Why is this not a problem?
There are two worlds: synchronization and asynchronous world. You can put things or take things from asynchronous wrold using! and take it! but others, then (and possibly some other functions), these worlds are separated from each other. clojure does not want to become completely asynchronous. Functions and data transformation are what you need to put together.
Perhaps, as a consequence of the previous two problems, a lot of code with core.async uses lower-level constructs such as loop / recur instead of map / filter / reduce. Isn't that a step back
An operation similar to these channels will be possible. Core.async is still young, and not all possible constructs and functions have been written yet.
But in the general case, if you have big data transformations, you really do not want to do them in the asynchronous world, you want them to be in a collection, and then throw something like a reduction structure on it.
The main thing to understand this, core.async is not a new standard, it is another thing that helps you in programming. Sometimes you need STM, sometimes agents, sometimes CSP, and clojure wants to provide you with all the options.
One of the reasons people love core.async is because it helps with some things that are really really hard to handle, such as callbacks.