Terry Reedy wrote:
Rasmus Fogh wrote:
Dear All,

For the first time I have come across a Python feature that seems
completely wrong. After the introduction of rich comparisons, equality
comparison does not have to return a truth value, and may indeed return
nothing at all and throw an error instead. As a result, code like
  if foo == bar:
or
  foo in alist
cannot be relied on to work.

This is clearly no accident. According to the documentation all comparison operators are allowed to return non-booleans, or to throw errors. There is
explicitly no guarantee that x == x is True.

You have touched on a real and known issue that accompanies dynamic typing and the design of Python. *Every* Python function can return any Python object and may raise any exception either actively, by design, or passively, by not catching exceptions raised in the functions *it* calls.

Personally I would like to get these [EMAIL PROTECTED]&* misfeatures removed,

What you are calling a misfeature is an absence, not a presence that can be removed.

That's not quite true. Rich comparisons explicitly allow non-boolean return values. Breaking up __cmp__ into multiple __special__ methods was not the sole purpose of rich comparisons. One of the prime examples at the time was numpy (well, Numeric at the time). We wanted to use == to be able to return an array with boolean values where the two operand arrays were equal. E.g.

In [1]: from numpy import *

In [2]: array([1, 2, 3]) == array([4, 2, 3])
Out[2]: array([False,  True,  True], dtype=bool)

SQLAlchemy uses these operators to build up objects that will be turned into SQL expressions.

>>> print users.c.id==addresses.c.user_id
users.id = addresses.user_id

Basically, the idea was to turn these operators into full-fledged operators like +-/*. Returning a non-boolean violates neither the letter, nor the spirit of the feature.

Unfortunately, if you do overload __eq__ to build up expressions or whatnot, the other places where users of __eq__ are implicitly expecting a boolean break. While I was (and am) a supporter of rich comparisons, I feel Rasmus's pain from time to time. It would be nice to have an alternate method to express the boolean "yes, this thing is equal in value to that other thing". Unfortunately, I haven't figured out a good way to fit it in now without sacrificing rich comparisons entirely.

and constrain the __eq__ function to always return a truth value.

It is impossible to do that with certainty by any mechanical creation-time checking. So the implementation of operator.eq would have to check the return value of the ob.__eq__ function it calls *every time*. That would slow down the speed of the 99.xx% of cases where the check is not needed and would still not prevent exceptions. And if the return value was bad, all operator.eq could do is raise and exception anyway.

Sure, but then it would be a bug to return a non-boolean from __eq__ and friends. It is not a bug today. I think that's what Rasmus is proposing.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
 that is made terrible by our own mad attempt to interpret it as though it had
 an underlying truth."
  -- Umberto Eco

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to