On Wed, Mar 18, 2015 at 2:48 PM, Petr Viktorin
On Wed, Mar 18, 2015 at 12:01 PM, M.-A. Lemburg
wrote: On 18.03.2015 11:53, Petr Viktorin wrote:
... I propose adding a public macro to ease this. My version takes two C-orderable values and the operation, similar to richcmpfunc:
#define Py_RICHCOMPARE(val1, val2, op) ( \ ((op) == Py_EQ) ? PyBool_FromLong((val1) == (val2)) : \ ((op) == Py_NE) ? PyBool_FromLong((val1) != (val2)) : \ ((op) == Py_LT) ? PyBool_FromLong((val1) < (val2)) : \ ((op) == Py_GT) ? PyBool_FromLong((val1) > (val2)) : \ ((op) == Py_LE) ? PyBool_FromLong((val1) <= (val2)) : \ ((op) == Py_GE) ? PyBool_FromLong((val1) >= (val2)) : \ (Py_INCREF(Py_NotImplemented), Py_NotImplemented))
(As for the behavior for unknown op: for most cases the best thing to do is setting an error and returning NULL, but that doesn't fit into a macro. A surprising number of richcmpfunc's in CPython either return NULL without error (e.g. tupleobject), or fall through and return True/False arbitrarily (as in bytearrayobject). Datetime does an assert. I think Py_NotImplemented is a good value to return) ... Is this a PEP-worthy idea?
This is a great idea, no need for a PEP :-) Please submit the patch on the bug tracker and also include a patch for the C API documentation.
Issue with patches is here: http://bugs.python.org/issue23699
Notes from the patch review: it is not so clear-cut after all. A sequence of comparisons is less efficient than a switch statement. Same with PyBool_FromLong vs. Py_RETURN_* Also, it might be too complex for a macro. These points could be solved by making it a function instead. Another issue raised is that the use cases are too limited limited for this to be a part of the Python API. I don't agree with that; I think boilerplate-reducing features are even if their usage is limited (see Py_RETURN_NOTIMPLEMENTED or PyModule_AddIntConstant).