
Tim Peters wrote: ...
This is a particularly simple application of coroutines that could be packaged up in a simpler way for its own sake; so, again, while continuations may be used fruitfully under the covers here, there's still no reason to make a poor end user wrestle with them.
Well. def longcomputation(prog, *args, **kw): return quickreturn(prog, args, kw) # prog must be something with return function first arg # quickreturn could be done as so: def quickreturn(prog, args, kw): cont = getpcc() # get parent's continuation def jumpback(val=None, cont=cont): putcc(cont, val) # jump to continuation apply(prog, jumpback, args, kw) # and if they want to jump out, they call jumpback with # an optional return value. Can't help it, it still is continuation-ish.
... Well, I admit that the continuation approach is slightly too much for the coroutine/generator case,
It's good that you admit that, because generators alone could have been implemented with a 20-line patch <wink>. BTW, I expect that by far the bulk of your changes *still* amount to what's needed for disentangling the C stack, right? The continuation implementation has been subtle, but so far I've gotten the impression that it requires little code beyond that required for stacklessness.
Right. You will see soon. The only bit which cont's need more than coro's is to save more than one stack state for a frame. So, basically, it is just the frame copy operation. If I was heading just for coroutines, then I could save that, but then I need to handle special cases like exception, what to do on return, and so on. Easier to do that one stuff once right. Then I will never dump code for an unforeseen coro-effect, since with cont's, I *may* jump in and bail out wherever I want or don't want. The special cases come later and will be optimized, and naturally they will reduce themselves to what's needed. Example: If I just want to switch to a different coro, I just have to swap two frames. This leads to a data structure which can hold a frame and exchange it with another one. The cont-implementation does something like fetch my current continuation # and this does the frame copy stuff save into local state variable fetch cont from other coro's local state variable jump to new cont Now, if the source and target frames are guaranteed to be different, and if the source frame has no dormant extra cont attached, then it is safe to merge the above steps into one operation, without the need to save local state. In the end, two coro's will jump to each other by doing nothing more than this. Exactly that is what Sam's prototype does right now. WHat he's missing is treatment of the return case. If a coro returns towards the place where it was forked off, then we want to have a cont which is able to handle it properly. That's why exceptions work fine with my stuff: You can put one exceptionhandler on top of all your coroutines which you create. It works without special knowledge of coroutines. After I realized that, I knew the way to go.
... How about "amb"? :-) (see "teach youself schem in fixnum days, chapter 14 at http://www.cs.rice.edu/~dorai/t-y-scheme/t-y-scheme-Z-H-15.html#%_chap_14)
That's the point at which I think continuations get insane: it's an unreasonably convoluted implementation of a straightforward (via other means) backtracking framework. In a similar vein, I've read 100 times that continuations can be used to implement a notion of (fake) threads, but haven't actually seen an implementation that wasn't depressingly subtle & long-winded despite being just a feeble "proof of concept".
Maybe this is a convoluted implementation. But the principle? Return a value to your caller, but stay able to continue and do this again. Two continuations, and with the optimizations from above, it will be nothing. I will show you the code in a few, and you will realize that we are discussing the empty set. The frames have to be used, and the frames are already continuations. Only if they can be reached twice, they will have to be armed for that. Moving back to my new "more code - less words" principle. [mutable ints as loop counters]
Ah, very clever! Yes, that will fly -- the continuations will share a reference to the value rather than the value itself. Perfect!
Actually I'm copying some code out of Marc's counterobject which is nothing more than a mutable integer and hide it in ceval.c, since that doesn't introduce another module for a thing which isn't needed elsewhere, after Guido's hint. Better than to use the array module which doesn't publish its internals and might not always be linked in.
Right, no downside at all. Except that Guido will hate it <wink>.
I made sure that this is what he hates the lest. off-for-coding-ly y'rs - chris -- Christian Tismer :^) <mailto:tismer@appliedbiometrics.com> Applied Biometrics GmbH : Have a break! Take a ride on Python's Kaiserin-Augusta-Allee 101 : *Starship* http://starship.python.net 10553 Berlin : PGP key -> http://wwwkeys.pgp.net PGP Fingerprint E182 71C7 1A9D 66E9 9D15 D3CC D4D7 93E2 1FAE F6DF we're tired of banana software - shipped green, ripens at home