In Clojure's core.async library we see a macro that creates a state machine that wraps around go
blocks to create channels that handle blocking IO.
This appears to be modelling on C#'s async
and on Go-lang's goroutines.
In The Seasoned Schemer - they describe techniques for passing continuations. (This appears to be based on call/cc). We also see a library from David Nolen on delimited continuations in Clojure.
Here they describe C#'s async
as 'call with current continuation'.
My question is can we describe Clojure's core.async as 'continuation passing style'?
Or are 'continuations' (delimited and undelimited) an overloaded term?
EDIT: On an additional note - David Nolen has said wrt to core.async:
Inside of a go block, it gives you the illusion that you can do these things in a synchronous manner so that you don’t have to write your code in continuation-passing style manually.
I see two questions here:
Is programming with core.async similar to programming in continuation-passing style?
Are the internals of core.async related to CPS?
The answer to 1. is "no", because there are no explicit continuations. In fact, this is kind of the point; one of the primary reasons for using core.async is to escape callback hell, which is basically CPS gone bad (callbacks being the continuations).
The simple answer to 2. is also "no", since the
go
macro uses an SSA internal representation to produce a state machine. It is true, however, that SSA and CPS are related in that they are used for similar purposes (that is, as internal representations in compilers; they feel different on the surface and aren't completely equivalent semantically, but in implementing something like core.async you could in principle use either one).