
[Greg Ewing]
What if the list contains a NaN?
[Armin Rigo]
Uh, right. The whole issue with NaNs is muddy. Let's focus on Numeric as a much saner example of why you need 'a==a' to return something else than True.
Yes. Please <wink>.
I belive that either my question was misinterpreted, or I'm missing something. I'm not suggesting to limit 'a==a' to return True/False only. I'm suggesting to introduce a shortcut in the *list* comparison (more specifically, in list_richcompare), since this is what is currently being done, but with a more expensive logic. Going through the function, in a case where v is w and op is either Py_EQ or Py_NE, we have 1) Both objects are lists, go on. 2) Both objects have the same size, go on. 3) Searching for the first index where items are different, using PyObject_RichCompareBool(), won't find anything. Go on. 4) No more items to compare. Check sizes. 5) Sizes match. Check comparison operator. 6) Return either Py_True or Py_False. This whole logic might be replaced by simply: if (v == w && (op == Py_EQ || op == Py_NE)) { res = (op == Py_EQ ? Py_True : Py_False); Py_INCREF(res); return res; } -- Gustavo Niemeyer http://niemeyer.net

Going through the function, in a case where v is w and op is either Py_EQ or Py_NE, we have
Looking again, this is true for any operation, not only Py_EQ or Py_NE. So the shortcut might be: if (v == w) { if (op == Py_EQ || op == Py_LE || op == Py_GE) res = Py_True; else res = Py_False; Py_INCREF(res); return res; } -- Gustavo Niemeyer http://niemeyer.net

[Gustavo Niemeyer]
I belive that either my question was misinterpreted, or I'm missing something.
Probably both, but who cares <wink>.
I'm not suggesting to limit 'a==a' to return True/False only. I'm suggesting to introduce a shortcut in the *list* comparison (more specifically, in list_richcompare), since this is what is currently being done, but with a more expensive logic.
What does "currently" mean to you? 2.3.3 and HEAD differ here.
Going through the function, in a case where v is w and op is either Py_EQ or Py_NE, we have
These cases aren't interesting on HEAD. Nobody calls list_richcompare directly. If something calls PyObject_RichCompareBool() with Py_EQ or Py_NE, then on HEAD the result is returned instantly, because of this code at the start of PyObject_RichCompareBool(): /* Quick result when objects are the same. Guarantees that identity implies equality. */ if (v == w) { if (op == Py_EQ) return 1; else if (op == Py_NE) return 0; } That code doesn't care whether v and w are lists or ints or Unicode strings or floats (etc). 2.3.3 doesn't have this code.
1) Both objects are lists, go on.
On HEAD, we don't get into list_richcompare.
2) Both objects have the same size, go on. 3) Searching for the first index where items are different, using PyObject_RichCompareBool(), won't find anything. Go on.
If v and w were created via, e.g., v = [] v.append(v) w = v then step #3 is a lot more complicated in 2.3.3 (because we recurse into list_richcompare repeatedly then, and a bunch of gone-on-HEAD machinery tries to notice that and guess the right result).
4) No more items to compare. Check sizes. 5) Sizes match. Check comparison operator. 6) Return either Py_True or Py_False.
This whole logic might be replaced by simply:
if (v == w && (op == Py_EQ || op == Py_NE)) { res = (op == Py_EQ ? Py_True : Py_False); Py_INCREF(res); return res; }
On HEAD, it has been replaced, but for all object types with one blow.

I'm not suggesting to limit 'a==a' to return True/False only. I'm suggesting to introduce a shortcut in the *list* comparison (more specifically, in list_richcompare), since this is what is currently being done, but with a more expensive logic.
What does "currently" mean to you? 2.3.3 and HEAD differ here.
I meant HEAD.
Going through the function, in a case where v is w and op is either Py_EQ or Py_NE, we have
These cases aren't interesting on HEAD. Nobody calls list_richcompare directly. If something calls PyObject_RichCompareBool() with Py_EQ or Py_NE, then on HEAD the result is returned instantly, because of this code at the start of PyObject_RichCompareBool():
I'm wondering what is causing this confusion then: % ./python Python 2.4a0 (#5, May 25 2004, 13:45:26) [GCC 3.3.3 (release)] on linux2 Type "help", "copyright", "credits" or "license" for more information. [...]
l = [] l == l Got in list_richcompare()! True if l == l: print "foo" ... Got in list_richcompare()! foo
-- Gustavo Niemeyer http://niemeyer.net

[Gustavo Niemeyer]
I'm wondering what is causing this confusion then:
% ./python Python 2.4a0 (#5, May 25 2004, 13:45:26) [GCC 3.3.3 (release)] on linux2 Type "help", "copyright", "credits" or "license" for more information. [...]
l = [] l == l Got in list_richcompare()! True if l == l: print "foo" ... Got in list_richcompare()! foo
My mistake! And my apologies. PyObject_RichCompare() (not ...Bool()) gets called in this case, and it can't infer anything from object identity alone. The list object may, but it's quite possible that trying to would cost more cycles than it saved.
participants (2)
-
Gustavo Niemeyer
-
Tim Peters