Sam Ruby
and Don Box have posted a couple of interesting articles on
continuations.  Sam’s article is a good explanation of what continuations
are for "old-timers" and gives a few examples in various domains.  However,
I was more intrigued by
Don
Box’ post
because it taught me that C# supports continuations, which I
didn’t know.

It’s quite refreshing to see a language take a few risks and implement
innovative features.  Time will tell if these features will find their
place in developers toolboxes, but right now, I will take this opportunity to
express a few doubts on the concept.

Don gives two examples, one written with continuations and one using
anonymous classes (delegates, actually, since C# supports those).  And the
first thing I notice is that both examples are about the same size and equally
readable to me.  This is not good for continuations, since I’m a firm
believer that if you introduce a new feature in a language, it needs to improve
at least one aspect of that language (readability, concision, performance,
etc…) radically.  If the new feature fails to achieve this goal, you now
have two slightly different ways to achieve the same thing, and Perl has already
taught us that this leads to the path of madness.

Something else that distresses me about continuations is that they are often
illustrated with Fibonacci or Web flow control.  These examples are quickly
turning into what logging is to AOP:  the quintessential example that
everybody understands but nobody can apply to their day job.

But here is the main problem I have with continuations:  how do you
debug them?

Out of curiosity, here is how you could implement Fibonacci in Java. 
First as an iterator:

class FibonacciIterator implements Iterator {
private int m_previous0 = 0;
private int m_previous1 = 1;
public void remove() {
// not implemented
}
public Object next() {
int result = m_previous0 + m_previous1;
m_previous0 = m_previous1;
m_previous1 = result;
return result;
}
public boolean hasNext() {
return true;
}
}

Implementing this as an Iterator makes it possible to use it in the
new for loop:

public class FibonacciContinuation implements Iterable {
public Iterator iterator() {
return new FibonacciIterator();
}
}

such as:

public static void main(String[] argv) {
int n = 10;
FibonacciContinuation fib = new FibonacciContinuation();
for (Object o : fib) {
System.out.println(o);
if (n-- <= 0) break;
}
}

which outputs:

1
2
3
5
8
13
21

This example is admittedly a little bit more verbose than Don’s, but it’s
because I wanted to make it fancy, and I contend that it has a big advantage
over a continuation-based implementation:  it can be debugged.

Imagine that your Fibonacci code has a bug and starts producing bogus values
after iteration 1057.  How do you trace the program there and how do you
inspect it, since all the state is implicitly maintained by the JVM (or whatever
runtime you are using)?

With the field-based approach to continuations, I get to decide and to define
what the state is, so that I can inspect it (and future readers of my code will
as well).

Does this mean that continuations are useless?  I wouldn’t go that far,
but it’s clear to me that Fibonacci is not the right way to advocate this
feature.  There have to be better examples where maintaining the state
explicitly like I did above would be too complex than the alternative (letting
the runtime do it for you) while still allowing you to debug easily through it.

I really want to like continuations, can somebody convince me with a good
example?