3 ms·
Because after tuple packing returns (a C return) you still need to perform a Python return. The C tuple packing function cannot return directly from the Python
by tom_mellior 6y ago
Because after tuple packing returns (a C return) you still need to perform a Python return. The C tuple packing function cannot return directly from the Python function.
Looking at https://github.com/python/cpython/blob/master/Python/ceval.c https://github.com/python/cpython/blob/master/Python/ceval.c, here is the code that needs to be executed after the tuple is constructed:
case TARGET(RETURN_VALUE): {
retval = POP();
assert(f->f_iblock == 0);
assert(EMPTY());
f->f_state = FRAME_RETURNED;
f->f_stackdepth = 0;
goto exiting;
}
// ...
exiting:
if (tstate->use_tracing) {
if (tstate->c_tracefunc) {
if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj,
tstate, f, PyTrace_RETURN, retval)) {
Py_CLEAR(retval);
}
}
if (tstate->c_profilefunc) {
if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj,
tstate, f, PyTrace_RETURN, retval)) {
Py_CLEAR(retval);
}
}
}
/* pop frame */
exit_eval_frame:
if (PyDTrace_FUNCTION_RETURN_ENABLED())
dtrace_function_return(f);
_Py_LeaveRecursiveCall(tstate);
tstate->frame = f->f_back;
return _Py_CheckFunctionResult(tstate, NULL, retval, __func__);
I guess you could duplicate all this code in a special "pack tuple and return from Python function" C function which you could then really tail call.
- eru 6y agoOh, yes, I was only saying that as far as the Python language is concerned the tuple packing is in the tail position. Any specific implementation, and in this case cpython, could do arbitrary weird things after. Thanks for looking up the code!