Out of the lengthy thread on tail call optimization has come one broad theory that might be of interest, so I'm spinning it off into its own thread.
The concept is like the Unix exec[vlpe] family of functions: replace the current stack frame with a new one. This can be used for explicit tail recursion without repeated stack frames, or for a pre-check that then disappears out of the stack. Like any other feature, it can be misused to make debugging difficult, but among consenting adults, hopefully it can be used sensibly. Examples: # derived from Paul Rubin's example def quicksort(array, start, end): midp = partition(array, start, end) if midp <= (start+end)//2: quicksort(array, start, midp) transfer quicksort(array, midp+1, end) else: quicksort(array, midp+1, end) transfer quicksort(array, start, midp) def count_usage(func): @functools.wraps(func) def wrapper(*args, **kwargs): wrapper.usage += 1 transfer func(*args, **kwargs) wrapper.usage = 0 return wrapper Semantics: * Evaluate the function and all its arguments, exactly as per a current function call. * Leaving them on the stack, remove the current call frame and dispose of all its objects. * Finally, construct a new stack frame for the target function and transfer control to it. In effect, "transfer f()" is equivalent to "return f()", except that the current function finishes before the target is entered. Note that this is incompatible with 'try' and 'with' blocks, and is disallowed inside them. It may be safe to use 'transfer' from a 'finally' block, and possibly from an 'except' block that isn't followed by a 'finally', but otherwise, there's code to be executed after the target returns, ergo it can't be done with a direct transfer. Open for bikeshedding: What should the keyword be? We can't use "exec", which would match Unix and shell usage, because it's already used in a rather different sense in Python. Current candidates: "transfer", "goto", "recurse", and anything else you suggest. Possible alternate syntax: transfer func[, (arg1, arg2, arg3)[, {'kw1': val1, 'kw2': val2}]] This makes it very clear that this is NOT accepting an arbitrary expression, but MUST be used with a single function and its arguments. Downside: It doesn't look like a function call any more. Upside: It's easy to parse. Also, if the argument sequence is mandatory instead of optional, this doesn't conflict with the simpler syntax (which wouldn't be allowed to have a comma after it), so one can be added now and another added later, if necessary. Is there anything that I've missed out in speccing this up? I've a suspicion that this might turn out to be as complicated as 'yield from' in all its handling of edge cases. ChrisA -- https://mail.python.org/mailman/listinfo/python-list