core.async has state (when buffers are used, in particular) but state is not exactly the same thing as mutability. Producers and consumers don't have unconstrained access to channels, in the way that users of a mutable cell (a Clojure atom, a ref cell, or just a variable in many languages) can clobber it at will.
Likewise (although I didn't get into this) state doesn't necessarily violate referential transparency. Memoization uses state as an optimization, but doesn't interfere with RT.
core.async has state (when buffers are used, in particular) but state is not exactly the same thing as mutability. Producers and consumers don't have unconstrained access to channels, in the way that users of a mutable cell (a Clojure atom, a ref cell, or just a variable in many languages) can clobber it at will.
Likewise (although I didn't get into this) state doesn't necessarily violate referential transparency. Memoization uses state as an optimization, but doesn't interfere with RT.