It reminded of all the talk in the 1980s and 1990s that self-modifying code is bad. But look at the elegant assignment to control-state within its body. It's such a poem, I thought I'd share it with people since nobody else blogs here anywya.

9
comments:

A pretty little ditty, to be sure. Much of object-oriented programming relies on self-modifying code, if you think about it. Consider the strategy pattern or the state pattern. In object-oriented programs it may appear that we are changing the data, but we are really changing the code.

@Gavin: Actually, it is exactly what the recent call/cc hype was about: To allow implicit (foreach) instead of explicit state machines, esp. in the context of web applications. Imagine the state getting a little bit more complicated. (You'd need to hide the call/cc in an abstraction for the generator programmer as well, though.)

call/cc is indeed a bad choice if all you're doing is making a generator out of a flat list. However, the technique mentioned works about equally well for turning folds over arbitrary data structures into generators/cursors.

For instance, writing a generator for a binary tree using only the analogues to car/cdr is a pain (I imagine you'd manage a stack of nodes to be visited by hand). However, writing an in-order traversal is simple. This example shows that you can turn the latter into the former automatically and generically using call/cc.

Of course, for the particular case of turning a fold into a cursor, delimited continuations are, perhaps, even nicer (and, in a sense, this example might be mimicking delimited continuations with call/cc + state). Something like:

This is a pretty cool example, but I think it would be clearer if the internal defines were desugared into a letrec. It's very odd to see a function definition mutated from inside the function in the first place, but somehow it seems more natural in a letrec. More importantly (for me at least), is that I can understand right away what the continuation of the letrec would be, but it's not at all obvious with the internal define -- it looks as though the continuation of the (define (generator) ...) code would continue by defining control-state again.