[Python-Dev] PEP 576/580: on the complexity of function calls
Now that the discussion on PEP 576/580 has been opened again, let me
write something about the complexity of function calls (*), which is
probably the most frequently given reason against PEP 580.
An important fact is the following: *the status-quo is complex*.
Over time, many performance improvements have been made to function
calls. Each of these was a relatively small incremental change (for
example, METH_FASTCALL with *args only was added before
METH_FASTCALL|METH_KEYWORDS with *args and **kwargs). In the end, all
these small changes add up to quite a bit of complexity. The fact that
this complexity isn't documented anywhere and that it's distributed over
several .c files in the CPython sources makes it perhaps not obvious
that it's there.
Neither PEP 576 nor PEP 580 tries to remove this complexity. Indeed, the
complexity is there for good reasons, as it improves performance of
function calls in many ways. But the PEPs handle it in very different ways.
On the one hand, PEP 580 concentrates all the complexity in the
protocol. So the protocol looks complex, even though most of it is
really just formulating existing complexity. More importantly, since the
complexity is moved to the protocol, it becomes quite easy to use PEP
580 in a class: you don't need to understand the implementation of PEP
580 for that.
On the other hand, PEP 576 keeps the existing complexity out of the
protocol. This means that the implementations of classes using PEP 576
become more complex, as the existing complexity needs to be implemented
somewhere. In fact, with PEP 576 the existing complexity needs to be
implemented in many places, leading for example to code duplication
between builtin_function_or_method and method_descriptor. This kind of
code duplication would again occur for third-party method-like classes.
Note that everything I said above about PEP 576 also applies to the
(*) With "function calls", I mean most importantly calls of instances of
builtin_function_or_method, method, method_descriptor and function. But
since PEP 576/580 are meant for third-party function/method classes,
also those should be considered.