[Python-Dev] RE: Rich comparisons [Was] redefining is (original) (raw)

Tim Peters tim.one at comcast.net
Sun Mar 21 01:26:10 EST 2004


[Raymond Hettinger]

... Essentially, I would like to insert the following lines into PyObjectRichCompare():

if (v == w) { if (op == PyEQ) PyRETURNTRUE; else if (op == PyNE) PyRETURNFALSE; }

At the sprint today, Armin Rigo pointed out that this specific kind of change is a non-starter: rich comparisons aren't constrained to return bools. In fact, that's primarily why they were introduced, so that the array extensions to Python could have (e.g.)

array1 == array2  # assuming same shapes

return an array of true/false values (recording elementwise equality of corresponding array elements). "array1 is array2" can't cause a special case returning a scalar then.

So that's right out.

OTOH, the changes we've made to recursive compares in 2.4 are causing Armin some grief, particularly wrt dicts that may be reachable from themselves. Doing, e.g.,

d = {} d[1] = d d == d

returns True in 2.3.3, but raises

RuntimeError: maximum recursion depth exceeded in cmp

in current CVS.

While PyObject_RichCompare() can't make any assumption about the return type, PyObject_RichCompareBool() can, and inserting

x is y

implies (x == y) is True

in the latter remains possible.

Armin and Guido and I agreed it's OK if

x = someNaN x == x True

happened as a result. Also that we're willing to insist that "x is y" implies "x == y" regardless of type in PyObject_RichCompareBool(). But since "x == x" doesn't normally invoke PyObject_RichCompareBool, the willingness to infer equality from identity in the latter may have no effect on NaN comparisons.

WRT the NaN business, Python doesn't have a real 754 story now, and what we've done so far in 2.4 to back into a teensy part of one by contrived accident isn't worth preserving. If we were serious about this, I'd argue until everyone gave up <0.4 wink> that "naive comparisons" involving NaNs should raise an exception, and that the 32(*) possible 754 comparisons be supplied via a wordier spelling (there are 16 depending on which subset of {less, equal, greater, unordered} you're asking about, and then each of those comes in two flavors, one that raises an exception if at least one comparand is a NaN, and another that doesn't -- "==", "<", "<=", ..., would then map to 6 of the first flavor, leaving 26 that could only be gotten via a wordier spelling).

I'd like Armin to share enough details here about the cases causing him grief now so that we can all guess whether that kind of change to PyObject_RichCompareBool would be enough to make life happy again.

(*) Note that not all 32 possibilities are actually useful; e.g., one of them always returns True, another always False. Similarly, when unordered isn't a possible outcome, there are 6 non-empty proper subsets of {less, equal, greater}, and that's where the 6 comparison operators "we're used to" come from (the {less, greater} subset being the "not equal" operator, which is screamingly obvious from its deprecated "<>" spelling).



More information about the Python-Dev mailing list