Carl Banks wrote: > Maybe look to see how tail-recursive optimization in languages such as > Scheme work, and whether it can be generalized.
Thanks for the feedback - I should've remembered tail recursion. > I doubt this would be possible without a major change in how functions > work in Python. The most obvious problem is that functions refer to > local variables by an index, not by name. If you were to execute the > bytecode of one function in the stack frame of another, Bad Things > would happen. Oh that's a pity. I can see why you'd do that, but it is a pity. That would tend to imply that _replacing_ rather than _reusing_ the top frame is the most doable/likely/sensible approach. (It's also very obviously easier to emulate) (And yes, I was consider reusing or replacing *only* the top stack frame. Replacing seems better with retrospect, even if reusing seemed like a fun idea :-) > > def set_name(): > > name = raw_input("Enter your name! > ") > > cexe greet() > > > > def greet(): > > print "hello", name > > > > cexe set_name() > > print "We don't reach here" > > ---------- > > > > This would execute, ask for the user's name, say hello to them and then > > exit - not reaching the final print "We don't reach here" statement. > > Only if you were to replace the whole stack. If you only replace or > reuse the top frame, I would think greet would exit and execution would > resume right after the point from which set_name was called. Or am I > misunderstanding what you want? I think you are. In the hypothetical example, your code by definition gets called by something. This leave a hypothetical return point. For the moment, lets make things clearer by what I mean by changing the example to this: > > 1 def set_name(): > > 2 name = raw_input("Enter your name! > ") > > 3 cexe greet() > > 4 > > 5 def greet(): > > 6 print "hello", name > > 7 > > 8 def main(): > > 9 cexe set_name() > > 10 print "We don't reach here" > > 11 > > 12 main() > > 13 print "see what I mean?" > > ---------- at line 12, we call 8. We can argue then our stack looks like this: [ { "context" : "main", pc : 8 }, { "context" : "__main__", pc : 12 }, ] (I'm going to push/pop at the front of the list) We reach line 9, before we execute the code there: [ { "context" : "main", pc : 9 }, { "context" : "__main__", pc : 12 }, ] After we execute, it does a cexe call of set_name, not a normal call of set_name. This causes the top stack frame to be _replaced_ : [ { "context" : "set_name", pc : 1 }, { "context" : "__main__", pc : 12 }, ] We then carry on, until we reach line 3, at which point before execution our stack would look something like: [ { "context" : "set_name", pc : 3 }, { "context" : "__main__", pc : 12 }, ] And after: [ { "context" : "greet", pc : 5 }, { "context" : "__main__", pc : 12 }, ] We'd then execute line 6, and after executing that line, our stack would look like this: [ { "context" : "greet", pc : 6 }, { "context" : "__main__", pc : 12 }, ] We're falling off the end of a function at that point, so we'd pop the top stack frame, as follows: [ { "context" : "__main__", pc : 12 }, ] Which means we return to the line after 12, and continue on with line 13 print "see what I mean". That means the '''print "We don't reach here"''' code isn't executed. >> * Am I mad? :) > > Yep. :) Thought so! Thanks :-) Michael. -- http://mail.python.org/mailman/listinfo/python-list