Stackless Python - Pros and Cons

Could the defenders of Stackless Python please explain _why_ this is such a great idea? Just and Christian seem to swear by it, but I'd like to hear of some simple examples of programming tasks that will be programmable in 50% less code with it (or 50% more understandable code, for that matter). And, similarly, could the detractors of Stackless Python explain why it is such a bad idea. A lot of core-pythoneers seem to have misgivings about it, even though issues of compatability and efficiency have been countered many times here by its champions (at least, it seems that way to a clueless bystander like myself). I'd really like to be able to take a firm standpoint myself, that's part of my personality, but I really don't know which firm standpoint at the moment:-) -- Jack Jansen | ++++ stop the execution of Mumia Abu-Jamal ++++ Jack.Jansen@oratrix.com | ++++ if you agree copy these lines to your sig ++++ www.oratrix.nl/~jack | ++++ see http://www.xs4all.nl/~tank/ ++++

[Jack Jansen]
Could the defenders of Stackless Python please explain _why_ this is such a great idea? ...
But they already have, and many times. That's why it needs a PEP: so we don't have to endure <wink> the exact same heated discussions multiple times every year for eternity.
... And, similarly, could the detractors of Stackless Python explain why it is such a bad idea.
Ditto. if-anyone-hasn't-yet-noticed-98%-of-advocacy-posts-go-straight- into-a-black-hole-ly y'rs - tim

On Sun, Aug 06, 2000 at 10:56:48PM +0200, Jack Jansen wrote:
Could the defenders of Stackless Python please explain _why_ this is such a great idea? Just and Christian seem to swear by it, but I'd like to hear of some simple examples of programming tasks that will be programmable in 50% less code with it (or 50% more understandable code, for that matter).
That's *continuations*, not Stackless. Stackless itself is just a way of implementing the Python bytecode eval loop with minimized use of the C stack. It doesn't change any functionality except the internal dependance on the C stack (which is limited on some platforms.) Stackless also makes a number of things possible, like continuations. Continuations can certainly reduce code, if used properly, and they can make it a lot more readable if the choice is between continuations or threaded spaghetti-code. It can, however, make code a lot less readable too, if used improperly, or when viewed by someone who doesn't grok continuations. I'm +1 on Stackless, +0 on continuations. (Continuations are cool, and Pythonic in one sense (stackframes become even firster class citizens ;) but not easy to learn or get used to.)
And, similarly, could the detractors of Stackless Python explain why it is such a bad idea.
I think my main reservation towards Stackless is the change to ceval.c, which is likely to be involved (I haven't looked at it, yet) -- but ceval.c isn't a childrens' book now, and I think the added complexity (if any) is worth the loss of some of the dependancies on the C stack. fl.0,02-ly y'rs, -- Thomas Wouters <thomas@xs4all.net> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

Jack Jansen <jack@oratrix.nl>:
Could the defenders of Stackless Python please explain _why_ this is such a great idea? Just and Christian seem to swear by it, but I'd like to hear of some simple examples of programming tasks that will be programmable in 50% less code with it (or 50% more understandable code, for that matter).
My interest in Stackless is that I want to see Icon-style generators, co-routining, and first-class continuations in Python. Generators and co-routining are wrappers around continuations. Something functionally equivalent to the Stackless mods is needed to get us there, because using the processor stack makes it very hard to do continuations properly. In their full generality, first-class continuations are hard to think about and to explain clearly, and I'm not going to try here. A large part of Guido's reluctance to introduce them is precisely because they are so hard to think about; he thinks it's a recipe for trouble stuff in the language that *he* has trouble understanding, let alone other people. He has a point, and part of the debate going on in the group that has been tracking this stuff (Guido, Barry Warsaw, Jeremy Hylton, Fred Drake, Eric Tiedemann and myself) is whether Python should expose support for first-class continuations or only "safer" packagings such as coroutining and generators. So for the moment just think of continuations as the necessary primitive to implement coroutining and generators. You can think of a generator as a function that, internally, is coded as a special kind of loop. Let's say, for example, that you want a function that returns successive entries in the list "squares of integers". In Python-with-generators, that would look something like this. def square_generator(): i = 1 while 1: yield i**2 i = i + 1 Calling this function five times in succession would return 1, 4, 9, 16, 25. Now what would be going on under the hood is that the new primitive "yield" says "return the given value, and save a continuation of this function to be run next time the function is called". The continuation saves the program counter and the state of automatic variables (the stack) to be restored on the next call -- thus, execution effectively resumes just after the yield statement. This example probably does not look very interesting. It's a very trivial use of the facility. But now suppose you had an analogous function implemented by a code loop that gets an X event and yields the event data! Suddenly, X programs don't have to look like a monster loop with all the rest of the code hanging off of them. Instead, any function in the program that needs to do stateful input parsing can just say "give me the next event" and get it. In general, what generators let you do is invert control hierarchies based on stateful loops or recursions. This is extremely nice for things like state machines and tree traversals -- you can bundle away the control loop away in a generator, interrupt it, and restart it without losing your place. I want this feature a lot. Guido has agreed in principle that we ought to have generators, but there is not yet a well-defined path forward to them. Stackless may be the most promising route. I was going to explain coroutines separately, but I realized while writing this that the semantics of "yield" proposed above actually gives full coroutining. Two functions can ping-pong control back and forth among themselves while retaining their individual stack states as a pair of continuations. -- <a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a> "This country, with its institutions, belongs to the people who inhabit it. Whenever they shall grow weary of the existing government, they can exercise their constitutional right of amending it or their revolutionary right to dismember it or overthrow it." -- Abraham Lincoln, 4 April 1861

[ Eric S. Raymond]
... I want this feature [generators] a lot. Guido has agreed in principle that we ought to have generators, but there is not yet a well-defined path forward to them. Stackless may be the most promising route.
Actually, if we had a PEP <wink>, it would have recorded for all time that Guido gave a detailed description of how to implement generators with minor changes to the current code. It would also record that Steven Majewski had already done so some 5 or 6 years ago. IMO, the real reason we don't have generators already is that they keep getting hijacked by continuations (indeed, Steven gave up on his patches as soon as he realized he couldn't extend his approach to continuations).
I was going to explain coroutines separately, but I realized while writing this that the semantics of "yield" proposed above actually gives full coroutining.
Well, the Icon semantics for "suspend"-- which are sufficient for Icon's generators --are not sufficient for Icon's coroutines. It's for that very reason that Icon supports generators on all platforms (including JCon, their moral equivalent of JPython), but supports coroutines only on platforms that have the magical blob of platform-dependent machine-language cruft needed to trick out the C stack at coroutine context switches (excepting JCon, where coroutines are implemented as Java threads). Coroutines are plain harder. Generators are just semi-coroutines (suspend/yield *always* return "to the caller", and that makes life 100x easier in a conventional eval loop like Python's -- it's still "stack-like", and the only novel thing needed is a way to resume a suspended frame but still in call-like fashion). and-if-we-had-a-pep-every-word-of-this-reply-would-have-been- in-it-too<wink>-ly y'rs - tim

Tim Peters <tim_one@email.msn.com>:
[ Eric S. Raymond]
... I want this feature [generators] a lot. Guido has agreed in principle that we ought to have generators, but there is not yet a well-defined path forward to them. Stackless may be the most promising route.
Actually, if we had a PEP <wink>, it would have recorded for all time that Guido gave a detailed description of how to implement generators with minor changes to the current code. It would also record that Steven Majewski had already done so some 5 or 6 years ago.
Christian Tismer, over to you. I am not going to presume to initiate the continuations PEP when there's someone with a Python implementation and extensive usage experience on the list. However, I will help with editing and critiques based on my experience with other languages that have similar features, if you want.
IMO, the real reason we don't have generators already is that they keep getting hijacked by continuations (indeed, Steven gave up on his patches as soon as he realized he couldn't extend his approach to continuations).
This report of repeated "hijacking" doesn't surprise me a bit. In fact, if I'd thought about it I'd have *expected* it. We know from experience with other languages (notably Scheme) that call-with-current-continuation is the simplest orthogonal primitive that this whole cluster of concepts can be based on. Implementors with good design taste are going to keep finding their way back to it, and they're going to feel incompleteness and pressure if they can't get there. This is why I'm holding out for continuation objects and call-with-continuation to be an explicit Python builtin. We're going to get there anyway; best to do it cleanly right away. -- <a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a> "Taking my gun away because I might shoot someone is like cutting my tongue out because I might yell `Fire!' in a crowded theater." -- Peter Venetoklis

[Tim]
IMO, the real reason we don't have generators already is that they keep getting hijacked by continuations (indeed, Steven gave up on his patches as soon as he realized he couldn't extend his approach to continuations).
[esr]
This report of repeated "hijacking" doesn't surprise me a bit. In fact, if I'd thought about it I'd have *expected* it. We know from experience with other languages (notably Scheme) that call-with- current-continuation is the simplest orthogonal primitive that this whole cluster of concepts can be based on. Implementors with good design taste are going to keep finding their way back to it, and they're going to feel incompleteness and pressure if they can't get there.
On the one hand, I don't think I know of a language *not* based on Scheme that has call/cc (or a moral equivalent). REBOL did at first, but after Joe Marshal left, Carl Sassenrath ripped it out in favor of a more conventional implementation. Even the massive Common Lisp declined to adopt call/cc, the reasons for which Kent Pitman has posted eloquently and often on comp.lang.lisp (basically summarized by that continuations are, in Kent's view, "a semantic mess" in the way Scheme exposed them -- btw, people should look his stuff up, as he has good ideas for cleaning that mess w/o sacrificing the power (and so the Lisp world splinters yet again?)). So call/cc remains "a Scheme thing" to me after all these years, and even there by far the most common warning in the release notes for a new implementation is that call/cc doesn't work correctly yet or at all (but, in the meantime, here are 3 obscure variations that will work in hard-to-explain special cases ...). So, ya, we *do* have experience with this stuff, and it sure ain't all good. On the other hand, what implementors other than Schemeheads *do* keep rediscovering is that generators are darned useful and can be implemented easily without exotic views of the world. CLU, Icon and Sather all fit in that box, and their designers wouldn't touch continuations with a 10-foot thick condom <wink>.
This is why I'm holding out for continuation objects and call-with-continuation to be an explicit Python builtin. We're going to get there anyway; best to do it cleanly right away.
This can get sorted out in the PEP. As I'm sure someone else has screamed by now (because it's all been screamed before), Stackless and the continuation module are distinct beasts (although the latter relies on the former). It would be a shame if the fact that it makes continuations *possible* were to be held against Stackless. It makes all sorts of things possible, some of which Guido would even like if people stopped throwing continuations in his face long enough for him to see beyond them <0.5 wink -- but he doesn't like continuations, and probably never will>.

[Tim]
On the one hand, I don't think I know of a language *not* based on Scheme that has call/cc (or a moral equivalent).
[Jeremy Hylton]
ML also has call/cc, at least the Concurrent ML variant.
So it does! I've found 3 language lines that have full-blown call/cc (not counting the early versions of REBOL, since they took it out later), and at least one web page claiming "that's all, folks": 1. Scheme + derivatives (but not including most Lisps). 2. Standard ML + derivatives (but almost unique among truly functional languages): http://cm.bell-labs.com/cm/cs/what/smlnj/doc/SMLofNJ/pages/cont.html That page is pretty much incomprehensible on its own. Besides callcc (no "/"), SML-NJ also has related "throw", "isolate", "capture" and "escape" functions. At least some of them *appear* to be addressing Kent Pitman's specific complaints about the excruciating interactions between call/cc and unwind-protect in Scheme. 3. Unlambda. This one is a hoot! Don't know why I haven't bumped into it before: http://www.eleves.ens.fr:8080/home/madore/programs/unlambda/ "Your Functional Programming Language Nightmares Come True" Unlambda is a deliberately obfuscated functional programming language, whose only data type is function and whose only syntax is function application: no lambdas (or other "special forms"), no integers, no lists, no variables, no if/then/else, ... call/cc is spelled with the single letter "c" in Unlambda, and the docs note "expressions including c function calls tend to be hopelessly difficult to track down. This was, of course, the reason for including it in the language in the first place". Not all frivolous, though! The page goes on to point out that writing an interpreter for Unlambda in something other than Scheme exposes many of the difficult issues (like implementing call/cc in a language that doesn't have any such notion -- which is, after all, almost all languages), in a language that's otherwise relentlessly simple-minded so doesn't bog you down with accidental complexities. Doesn't mean call/cc sucks, but language designers *have* been avoiding it in vast numbers -- despite that the Scheme folks have been pushing it (& pushing it, & pushing it) in every real language they flee to <wink>. BTW, lest anyone get the wrong idea, I'm (mostly) in favor of it! It can't possibly be sold on any grounds other than that "it works, for real Python programmers with real programming problems they can't solve in other ways", though. Christian has been doing a wonderful (if slow-motion <wink>) job of building that critical base of real-life users.

Tim Peters <tim_one@email.msn.com>:
Doesn't mean call/cc sucks, but language designers *have* been avoiding it in vast numbers -- despite that the Scheme folks have been pushing it (& pushing it, & pushing it) in every real language they flee to <wink>.
Yes, we have. I haven't participated in conspiratorial hugggermugger with other ex-Schemers, but I suspect we'd all answer pretty much the same way. Lots of people have been avoiding call/cc not because it sucks but but because the whole area is very hard to think about even if you have the right set of primitives.
BTW, lest anyone get the wrong idea, I'm (mostly) in favor of it! It can't possibly be sold on any grounds other than that "it works, for real Python programmers with real programming problems they can't solve in other ways", though. Christian has been doing a wonderful (if slow-motion <wink>) job of building that critical base of real-life users.
And it's now Christian's job to do the next stop, supplying up-to-date documentation on his patch and proposal as a PEP. Suggestion: In order to satisfy the BDFL's conservative instincts, perhaps it would be better to break the Stackless patch into two pieces -- one that de-stack-izes ceval, and one that implements new language features. That way we can build a firm base for later exploration. -- <a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a> "Government is not reason, it is not eloquence, it is force; like fire, a troublesome servant and a fearful master. Never for a moment should it be left to irresponsible action." -- George Washington, in a speech of January 7, 1790

Jack Jansen wrote:
Could the defenders of Stackless Python please explain _why_ this is such a great idea? Just and Christian seem to swear by it, but I'd like to hear of some simple examples of programming tasks that will be programmable in 50% less code with it (or 50% more understandable code, for that matter).
Here's the complete code for the download of a file (the data connection of an FTP server): def _doDnStream(self, binary=0): mode = 'r' if binary: mode = mode + 'b' f = open(self.cmdconn.filename, mode) if self.cmdconn.filepos: #XXX check length of file f.seek(self.cmdconn.filepos, 0) while 1: if self.abort: break data = f.read(8192) sz = len(data) if sz: if not binary: data = '\r\n'.join(data.split('\n')) self.write(data) if sz < 8192: break [from the base class] def write(self, msg): while msg: sent = self.dispatcher.write(self.sock, msg) if sent == 0: raise IOError, "unexpected EOF" msg = msg[sent:] Looks like blocking sockets, right? Wrong. That's a fully multiplexed socket. About a dozen lines of code (hidden in that dispatcher object) mean that I can write async without using a state machine. stackless-forever-ly y'rs - Gordon

If someone is going to write a PEP, I hope they will explain how the implementation deals with the various Python C API calls that can call back into Python. In the stackless implementation, builtin_apply is a thin wrapper around builtin_apply_nr. The wrapper checks the return value from builtin_apply_nr for Py_UnwindToken. If Py_UnwindToken is found, it calls PyEval_Frame_Dispatch. In this case, builtin_apply returns whatever PyEval_Frame_Dispatch returns; the frame dispatcher just executes stack frames until it is ready to return. How does this control flow at the C level interact with a Python API call like PySequence_Tuple or PyObject_Compare that can start executing Python code again? Say there is a Python function call which in turn calls PySequence_Tuple, which in turn calls a __getitem__ method on some Python object, which in turn uses a continuation to transfer control. After the continuation is called, the Python function will never return and the PySquence_Tuple call is no longer necessary, but there is still a call to PySequence_Tuple on the C stack. How does stackless deal with the return through this function? I expect that any C function that may cause Python code to be executed must be wrapped the way apply was wrapper. So in the example, PySequence_Tuple may return Py_UnwindToken. This adds an extra return condition that every caller of PySequence_Tuple must check. Currently, the caller must check for NULL/exception in addition to a normal return. With stackless, I assume the caller would also need to check for "unwinding." Is this analysis correct? Or is there something I'm missing? I see that the current source release of stackless does not do anything special to deal with C API calls that execute Python code. For example, PyDict_GetItem calls PyObject_Hash, which could in theory lead to a call on a continuation, but neither caller nor callee does anything special to account for the possibility. Is there some other part of the implementation that prevents this from being a problem? Jeremy

Jeremy Hylton wrote:
If someone is going to write a PEP, I hope they will explain how the implementation deals with the various Python C API calls that can call back into Python.
He will.
In the stackless implementation, builtin_apply is a thin wrapper around builtin_apply_nr. The wrapper checks the return value from builtin_apply_nr for Py_UnwindToken. If Py_UnwindToken is found, it calls PyEval_Frame_Dispatch. In this case, builtin_apply returns whatever PyEval_Frame_Dispatch returns; the frame dispatcher just executes stack frames until it is ready to return.
Correct.
How does this control flow at the C level interact with a Python API call like PySequence_Tuple or PyObject_Compare that can start executing Python code again? Say there is a Python function call which in turn calls PySequence_Tuple, which in turn calls a __getitem__ method on some Python object, which in turn uses a continuation to transfer control. After the continuation is called, the Python function will never return and the PySquence_Tuple call is no longer necessary, but there is still a call to PySequence_Tuple on the C stack. How does stackless deal with the return through this function?
Right. What you see here is the incompleteness of Stackless. In order to get this "right", I would have to change many parts of the implementation, in order to allow for continuations in every (probably even unwanted) place. I could not do this. Instead, the situation of these still occouring recursions are handled differently. continuationmodule guarantees, that in the context of recursive interpreter calls, the given stack order of execution is obeyed. Violations of this cause simply an exception.
I expect that any C function that may cause Python code to be executed must be wrapped the way apply was wrapper. So in the example, PySequence_Tuple may return Py_UnwindToken. This adds an extra return condition that every caller of PySequence_Tuple must check. Currently, the caller must check for NULL/exception in addition to a normal return. With stackless, I assume the caller would also need to check for "unwinding."
No, nobody else is allowed to return Py_UnwindToken but the few functions in the builtins implementation and in ceval. The continuationmodule may produce it since it knows the context where it is called. eval_code is supposed to be the main instance who checks for this special value. As said, allowing this in any context would have been a huge change to the whole implementation, and would probably also have broken existing extensions which do not expect that a standard function wants to do a callback.
Is this analysis correct? Or is there something I'm missing?
I see that the current source release of stackless does not do anything special to deal with C API calls that execute Python code. For example, PyDict_GetItem calls PyObject_Hash, which could in theory lead to a call on a continuation, but neither caller nor callee does anything special to account for the possibility. Is there some other part of the implementation that prevents this from being a problem?
This problem is no problem for itself, since inside the stackless modification for Python, there are no places where unexpected Py_UnwindTokens or continuations are produced. This is a closed system insofar. But with the continuation extension, it is of course a major problem. The final solution to the recursive interpreter/continuation problem was found long after my paper was presented. The idea is simple, solves everything, and shortened my implementation substantially: Whenever a recursive interpreter call takes place, the calling frame gets a lock flag set. This flag says "this frame is wrapped in a suspended eval_code call and cannot be a continuation". continuationmodule always obeys this flag and prevends the creation of continuations for such frames by raising an exception. In other words: Stack-like behavior is enforced in situations where the C stack is involved. So, a builtin or an extension *can* call a continuation, but finally, it will have to come back to the calling point. If not, then one of the locked frames will be touched, finally, in the wrong C stack order. But by reference counting, this touching will cause the attempt to create a continuation, and what I said above will raise an exception. Probably the wrong place to explain this in more detail here, but it doesn't apply to the stackless core at all which is just responsible for the necessary support machinery. ciao - chris -- Christian Tismer :^) <mailto:tismer@appliedbiometrics.com> Applied Biometrics GmbH : Have a break! Take a ride on Python's Kaunstr. 26 : *Starship* http://starship.python.net 14163 Berlin : PGP key -> http://wwwkeys.pgp.net PGP Fingerprint E182 71C7 1A9D 66E9 9D15 D3CC D4D7 93E2 1FAE F6DF where do you want to jump today? http://www.stackless.com

"CT" == Christian Tismer <tismer@appliedbiometrics.com> writes:
If someone is going to write a PEP, I hope they will explain how the implementation deals with the various Python C API calls that can call back into Python.
CT> He will. Good! You'll write a PEP.
How does this control flow at the C level interact with a Python API call like PySequence_Tuple or PyObject_Compare that can start executing Python code again? Say there is a Python function call which in turn calls PySequence_Tuple, which in turn calls a __getitem__ method on some Python object, which in turn uses a continuation to transfer control. After the continuation is called, the Python function will never return and the PySquence_Tuple call is no longer necessary, but there is still a call to PySequence_Tuple on the C stack. How does stackless deal with the return through this function?
CT> Right. What you see here is the incompleteness of Stackless. In CT> order to get this "right", I would have to change many parts of CT> the implementation, in order to allow for continuations in every CT> (probably even unwanted) place. I could not do this. CT> Instead, the situation of these still occouring recursions are CT> handled differently. continuationmodule guarantees, that in the CT> context of recursive interpreter calls, the given stack order of CT> execution is obeyed. Violations of this cause simply an CT> exception. Let me make sure I understand: If I invoke a continuation when there are extra C stack frames between the mainloop invocation that captured the continuation and the call of the continuation, the interpreter raises an exception? If so, continuations don't sound like they would mix well with C extension modules and callbacks. I guess it also could not be used inside methods that implement operator overloading. Is there a simple set of rules that describe the situtations where they will not work? Jeremy

[about recursion and continuations]
CT> Right. What you see here is the incompleteness of Stackless. In CT> order to get this "right", I would have to change many parts of CT> the implementation, in order to allow for continuations in every CT> (probably even unwanted) place. I could not do this.
CT> Instead, the situation of these still occouring recursions are CT> handled differently. continuationmodule guarantees, that in the CT> context of recursive interpreter calls, the given stack order of CT> execution is obeyed. Violations of this cause simply an CT> exception.
Let me make sure I understand: If I invoke a continuation when there are extra C stack frames between the mainloop invocation that captured the continuation and the call of the continuation, the interpreter raises an exception?
Not always. Frames which are not currently bound by an interpreter acting on them can always be jump targets. Only those frames which are currently in the middle of an opcode are forbidden.
If so, continuations don't sound like they would mix well with C extension modules and callbacks. I guess it also could not be used inside methods that implement operator overloading. Is there a simple set of rules that describe the situtations where they will not work?
Right. In order to have good mixing with C callbacks, extra work is necessary. The C extension module must then play the same frame dribbling game as the eval_loop does. An example can be found in stackless map. If the C extension does not do so, it restricts execution order in the way I explained. This is not always needed, and it is no new requirement for C developers to do so. Only if they want to support free continuation switching, they have to implement it. The simple set of rules where continuations will not work at the moment is: Generally it does not work across interpreter recursions. At least restrictions appear: - you cannot run an import and jump off to the caller's frame + but you can save a continuation in your import and use it later, when this recursive interpreter is gone. - all special class functions are restricted. + but you can for instance save a continuation in __init__ and use it later, when the init recursion has gone. Reducing all these restrictions is a major task, and there are situations where it looks impossible without an extra subinterpreter language. If you look into the implementation of operators like __add__, you will see that there are repeated method calls which all may cause other interpreters to show up. I tried to find a way to roll these functions out in a restartable way, but it is quite a mess. The clean way to do it would be to have microcodes, and to allow for continuations to be caught between them. this-is-a-stackless-3000-feature - ly y'rs - chris -- Christian Tismer :^) <mailto:tismer@appliedbiometrics.com> Applied Biometrics GmbH : Have a break! Take a ride on Python's Kaunstr. 26 : *Starship* http://starship.python.net 14163 Berlin : PGP key -> http://wwwkeys.pgp.net PGP Fingerprint E182 71C7 1A9D 66E9 9D15 D3CC D4D7 93E2 1FAE F6DF where do you want to jump today? http://www.stackless.com

Jeremy wrote:
"CT" == Christian Tismer <tismer@appliedbiometrics.com> writes:
If someone is going to write a PEP, I hope they will explain how >> the implementation deals with the various Python C API calls that >> can call back into Python.
CT> He will.
Good! You'll write a PEP.
Actually, "He" is me. While I speak terrible German, my Tismerish is pretty good (Tismerish to English is a *huge* jump <wink>). But I can't figure out what the h*ll is being PEPed. We know that continuations / coroutines / generators have great value. We know that stackless is not continuations; it's some mods (mostly to ceval.c) that enables continuation.c. But the questions you're asking (after protesting that you want a formal spec, not a reference implementation) are all about Christian's implementation of continuation.c. (Well, OK, it's whether the stackless mods are enough to allow a perfect continuations implementation.) Assuming that stackless can get along with GC, ceval.c and grammar changes (or Christian can make it so), it seems to me the PEPable issue is whether the value this can add is worth the price of a less linear implementation. still-a-no-brainer-to-me-ly y'rs - Gordon

Gordon, Thanks for channeling Christian, if that's what writing a PEP on this entails :-). I am also a little puzzled about the subject of the PEP. I think you should hash it out with Barry "PEPmeister" Warsaw. There are two different issues -- the stackless implementation and the new control structure exposed to programmers (e.g. continuations, coroutines, iterators, generators, etc.). It seems plausible to address these in two different PEPs, possibly in competing PEPs (e.g. coroutines vs. continuations). Jeremy

Gordon McMillan wrote:
But I can't figure out what the h*ll is being PEPed. ... Assuming that stackless can get along with GC,
As long as frames are not considered for GC, don't worry about GC.
ceval.c and grammar changes (or Christian can make it so), it seems to me the PEPable issue is whether the value this can add is worth the price of a less linear implementation.
There's an essay + paper available, slides and an implementation. What's the problem about formalizing this in a PEP and addressing the controversial issues + explaining how they are dealt with? I mean, if you're a convinced long-time Stackless user and everything is obvious for you, this PEP should try to convince the rest of us -- so write it down and ask no more <wink>. -- Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252

Vladimir Marangozov wrote:
Gordon McMillan wrote:
But I can't figure out what the h*ll is being PEPed. ...
...
ceval.c and grammar changes (or Christian can make it so), it seems to me the PEPable issue is whether the value this can add is worth the price of a less linear implementation.
There's an essay + paper available, slides and an implementation.
Of which the most up to date is the implementation. The slides / docs describe an earlier, more complex scheme.
What's the problem about formalizing this in a PEP and addressing the controversial issues + explaining how they are dealt with?
That's sort of what I was asking. As far as I can tell, what's controversial is "continuations". That's not in scope. I would like to know what controversial issues there are that *are* in scope.
I mean, if you're a convinced long-time Stackless user and everything is obvious for you, this PEP should try to convince the rest of us -- so write it down and ask no more <wink>.
That's exactly wrong. If that were the case, I would be forced to vote -1 on any addition / enhancement to Python that I personally didn't plan on using. - Gordon

Gordon McMillan wrote:
What's the problem about formalizing this in a PEP and addressing the controversial issues + explaining how they are dealt with?
That's sort of what I was asking. As far as I can tell, what's controversial is "continuations". That's not in scope. I would like to know what controversial issues there are that *are* in scope.
Here's the context that might help you figure out what I'd like to see in this PEP. I haven't been at the last conference, I have read the source and the essay as of years ago and have no idea that the most up to date thing is the implementation, which I refuse to look at again, btw, without a clear summary of what this code does, refreshing my memory on the whole subject. I'd like to see an overview of the changes, their expected impact on the core, the extensions, and whatever else you judge worthy to write about. I'd like to see a summary of the reactions that have been emitted and what issues are non-issues for you, and which ones are. I'd like to see a first draft giving me a horizontal view on the subject in its entirety. Code examples are welcome, too. I can then start thinking about it in a more structured way on this basis. I don't have such a basis right now, because there's no an up to date document in plain English that allows me to do that. And without such a document, I won't do it. it's-simple-<wink>'ly y'rs -- Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
participants (9)
-
Christian Tismer
-
Eric S. Raymond
-
Gordon McMillan
-
Jack Jansen
-
Jeremy Hylton
-
Jeremy Hylton
-
Thomas Wouters
-
Tim Peters
-
Vladimir.Marangozov@inrialpes.fr