Writing code in Go is the most fun I've had programming in years, mostly because of the way it handles these concurrency issues without dropping into callback hell.
December 24, 2012 at 11:04 AM
Being pedantic while I'm on the topic. We've covered this before.
Any language with lambdas (that can be fired when an async completes) can simulate coroutines.
Assume we have some async function call :
futureint> AsyncFunc( int x );
which send the integer off over the net (or whatever) and eventually gets a result back. Assume
that future<> has a "AndThen" which schedules a function to run when it's done.
Then you can write a sequence of operations like :
futureint> MySequenceOfOps( int x1 )
{
x1++;
futureint> f1 = AsyncFunc(x1);
return f1.AndThen( [](int x2){
x2 *= 2;
futureint> f2 = AsyncFunc(x2);
return f2.AndThen( [](int x3){
x3 --;
return x3;
} );
} );
}
with a little munging we can make it look more like a standard coroutine :
#define YIELD(future,args) return future.AndThen( [](args){
futureint> MySequenceOfOps( int x1 )
{
x1++;
futureint> f1 = AsyncFunc(x1);
YIELD(f1,int x2)
x2 *= 2;
futureint> f2 = AsyncFunc(x2);
YIELD(f2,int x3)
x3 --;
return x3;
} );
} );
}
the only really ugly bit is that you have to put a bunch of scope-closers at the end to match the number of
yields.
This is really what any coroutine is doing under the hood. When you hit a "yield", what it does is take
the remainder of the function and package that up as a functor to get called after the async op that you're
yielding on is done.
Coroutines from lambdas have a few disadvantages, aside from the scope-closers annoyance. It's ugly to do
anything but simple linear control flow. The above example is the very simple case of "imperative, yield, imperative,
yield" , but in real code you want to have things like :
if ( bool )
{
YIELD
}
or
while ( some condition )
{
YIELD
}
which while probably possible with lambda-coroutines, gets ugly.
An advantage of lambda-coroutines is if you're in a language where you have lambdas with variable-capture,
then you get that in your coroutines.
"12-21-12 - Coroutines From Lambdas"
3 Comments -
See also: Continuation-passing-style, and all async functions in node.js.
December 21, 2012 at 4:59 PM
Yup. My only point here really is that they are mostly equivalent.
Holy cow though I find CPS code to be impossible to read and impossible to debug.
We're getting more and more of it in the world and good god is it ugly.
Callbacks are a nasty nasty way to write code.
December 21, 2012 at 5:06 PM
Writing code in Go is the most fun I've had programming in years, mostly because of the way it handles these concurrency issues without dropping into callback hell.
December 24, 2012 at 11:04 AM