Re: [Python-Dev] PEP 207 -- Rich Comparisons
Guido van Rossum writes:
1. The current boolean operator behavior does not have to change, and hence will be backward compatible.
What incompatibility do you see in the current proposal?
You have to choose between using rich comparisons or boolean comparisons. You can't use both for the same (rich/complex) object.
2. It eliminates the need to decide whether or not rich comparisons takes precedence over boolean comparisons.
Only if you want different semantics -- that's only an issue for NumPy.
No. I think NumPy is the tip of the iceberg, when discussing new semantics. Most users don't consider these broader semantic issues, because Python doesn't give them the opportunity to do so. I can see possible scenarios of using both boolean and non-boolean comparisons for Python lists and dictionaries in addition to NumPy. I chose to use Python because it provides a richer framework than other languages. When Python fails to provide such benefits, I'll move to another language. I moved from PERL to Python because the multi-dimensional array syntax is vastly better in Python than PERL, though as a novice I don't have to know that it exists. What I'm proposing here is in a similar vein.
3. The new operators add additional behavior without directly impacting current behavior and the use of them is unambigous, at least in relation to current Python behavior. You know by the operator what type of comparison will be returned. This should appease Jim Fulton, based on his arguments in 1998 about comparison operators always returning a boolean value.
As you know, I'm now pretty close to Jim. :-) He seemed pretty mellow about this now.
Yes, I would hope so! It appears though that you misunderstand me. My point was that I tend to agree with Jim Fulton's arguments for a limited interpretation of the current comparison operators. I too expect them to return a boolean result. I have never felt comfortable using such comparison operators in an array context, e.g. as in the array language, IDL. It just looks wrong. So my suggestion is to create new ones whose implicit meaning is to provide element-wise or rich comparison behavior. And to add similar behavior for the other operators for consistency. Can someone provide an example in mathematics where comparison operators are used in a non-boolean, ie. rich comparison, context. If so, this might shut me up!
4. Compound objects, such as lists, could implement both rich and boolean comparisons. The boolean comparison would remain as is, while the rich comparison would return a list of boolean values. Current behavior doesn't change; just a new feature, which you may or may not choose to use, is added.
If we go one step further and add the matrix-style operators along with the comparison operators, we can provide a consistent user interface to array/complex operations without changing current Python behavior. If a user has no need for these new operators, he doesn't have to use them or even know about them. All we've done is made Python richer, but I believe with making it more complex. For
Phrase should be: "but I believe without making it more complex.". -------
example, all element-wise operations could have a ':' appended to them, e.g. '+:', '<:', etc.; and will define element-wise addition, element-wise less-than, etc. The traditional '*', '/', etc. operators can then be used for matrix operations, which will appease the Matlab people.
Therefore, I don't think rich comparisons and matrix-type operators should be considered separable. I really think you should consider this suggestion. It appeases many groups while providing a consistent and clear user interface, while greatly impacting current Python behavior.
The last phrase should read: "while not greatly impacting current --- Python behavior."
Always-causing-havoc-at-the-last-moment-ly Yours,
I think you misunderstand. Rich comparisons are mostly about allowing the separate overloading of <, <=, ==, !=, >, and >=. This is useful in its own light.
No, I do understand. I've read most of the early discussions on this issue and one of those issues was about having to choose between boolean and rich comparisons and what should take precedence, when both may be appropriate. I'm suggesting an alternative here.
If you don't want to use this overloading facility for elementwise comparisons in NumPy, that's fine with me. Nobody says you have to -- it's just that you *could*.
Yes, I understand.
Red my lips: there won't be *any* new operators in 2.1.
OK, I didn't expect this to make it into 2.1.
There will a better way to overload the existing Boolean operators, and they will be able to return non-Boolean results. That's useful in other situations besides NumPy.
Yes, I agree, this should be done anyway. I'm just not sure that the implicit meaning that these comparison operators are being given is the best one. I'm just looking for ways to incorporate rich comparisons into a broader framework, numpy just currently happens to be the primary example of this proposal. Assuming the current comparison operator overloading is already implemented and has been used to implement rich comparisons for some objects, then my rich comparison proposal would cause confusion. This is what I'm trying to avoid.
Feel free to lobby for elementwise operators -- but based on the discussion about this subject so far, I don't give it much of a chance even past Python 2.1. They would add a lot of baggage to the language (e.g. the table of operators in all Python books would be about twice as long) and by far the most users don't care about them. (Read the intro to 211 for some of the concerns -- this PEP tries to make the addition palatable by adding exactly *one* new operator.)
So! Introductory books don't have to discuss these additional operators. I don't have to know about XML and socket modules to start using Python effectively, nor do I have to know about 'zip' or list comprehensions. These additions decrease the code size and increase efficiency, but don't really add any new expressive power that can't already be done by a 'for' loop. I'll try to convince myself that this suggestion is crazy and not bother you with this issue for awhile. Cheers, Paul
Paul Barret:
1. The current boolean operator behavior does not have to change, and hence will be backward compatible.
Guido van Rossum:
What incompatibility do you see in the current proposal?
Paul Barret:
You have to choose between using rich comparisons or boolean comparisons. You can't use both for the same (rich/complex) object.
Sure. I thought that the NumPy folks were happy with this. Certainly two years ago they seemed to be.
2. It eliminates the need to decide whether or not rich comparisons takes precedence over boolean comparisons.
Only if you want different semantics -- that's only an issue for NumPy.
No. I think NumPy is the tip of the iceberg, when discussing new semantics. Most users don't consider these broader semantic issues, because Python doesn't give them the opportunity to do so. I can see possible scenarios of using both boolean and non-boolean comparisons for Python lists and dictionaries in addition to NumPy.
That's the same argument that has been made for new operators all along. I've explained already why they are not on the table for 2.1.
I chose to use Python because it provides a richer framework than other languages. When Python fails to provide such benefits, I'll move to another language. I moved from PERL to Python because the multi-dimensional array syntax is vastly better in Python than PERL, though as a novice I don't have to know that it exists. What I'm proposing here is in a similar vein.
3. The new operators add additional behavior without directly impacting current behavior and the use of them is unambigous, at least in relation to current Python behavior. You know by the operator what type of comparison will be returned. This should appease Jim Fulton, based on his arguments in 1998 about comparison operators always returning a boolean value.
As you know, I'm now pretty close to Jim. :-) He seemed pretty mellow about this now.
Yes, I would hope so!
It appears though that you misunderstand me. My point was that I tend to agree with Jim Fulton's arguments for a limited interpretation of the current comparison operators. I too expect them to return a boolean result. I have never felt comfortable using such comparison operators in an array context, e.g. as in the array language, IDL. It just looks wrong. So my suggestion is to create new ones whose implicit meaning is to provide element-wise or rich comparison behavior. And to add similar behavior for the other operators for consistency.
Can someone provide an example in mathematics where comparison operators are used in a non-boolean, ie. rich comparison, context. If so, this might shut me up!
Not me (I no longer consider myself a mathematician :-). Why are you
requiring an example from math though?
Again, you will be able to make this argument to the NumPy folks when
they are ready to change the meaning of A
4. Compound objects, such as lists, could implement both rich
and boolean comparisons. The boolean comparison would remain as
is, while the rich comparison would return a list of boolean
values. Current behavior doesn't change; just a new feature, which
you may or may not choose to use, is added. If we go one step further and add the matrix-style operators along
with the comparison operators, we can provide a consistent user
interface to array/complex operations without changing current Python
behavior. If a user has no need for these new operators, he doesn't
have to use them or even know about them. All we've done is made
Python richer, but I believe with making it more complex. For Phrase should be: "but I believe without making it more complex.".
------- example, all element-wise operations could have a ':' appended to
them, e.g. '+:', '<:', etc.; and will define element-wise addition,
element-wise less-than, etc. The traditional '*', '/', etc. operators
can then be used for matrix operations, which will appease the Matlab
people. Therefore, I don't think rich comparisons and matrix-type operators
should be considered separable. I really think you should consider
this suggestion. It appeases many groups while providing a consistent
and clear user interface, while greatly impacting current Python
behavior. The last phrase should read: "while not greatly impacting current
---
Python behavior."
I don't see any argument for elementwise operators here that I haven't heard before, and AFAIK it's all in the two PEPs.
Always-causing-havoc-at-the-last-moment-ly Yours,
I think you misunderstand. Rich comparisons are mostly about allowing the separate overloading of <, <=, ==, !=, >, and >=. This is useful in its own light.
No, I do understand. I've read most of the early discussions on this issue and one of those issues was about having to choose between boolean and rich comparisons and what should take precedence, when both may be appropriate. I'm suggesting an alternative here.
Note that Python doesn't decide which should take precedent. The implementer of an individual extension type decides what his comparison operators will return.
If you don't want to use this overloading facility for elementwise comparisons in NumPy, that's fine with me. Nobody says you have to -- it's just that you *could*.
Yes, I understand.
Red my lips: there won't be *any* new operators in 2.1.
OK, I didn't expect this to make it into 2.1.
There will a better way to overload the existing Boolean operators, and they will be able to return non-Boolean results. That's useful in other situations besides NumPy.
Yes, I agree, this should be done anyway. I'm just not sure that the implicit meaning that these comparison operators are being given is the best one. I'm just looking for ways to incorporate rich comparisons into a broader framework, numpy just currently happens to be the primary example of this proposal.
Assuming the current comparison operator overloading is already implemented and has been used to implement rich comparisons for some objects, then my rich comparison proposal would cause confusion. This is what I'm trying to avoid.
AFAIK, rich comparisons haven't been used anywhere to return non-Boolean results.
Feel free to lobby for elementwise operators -- but based on the discussion about this subject so far, I don't give it much of a chance even past Python 2.1. They would add a lot of baggage to the language (e.g. the table of operators in all Python books would be about twice as long) and by far the most users don't care about them. (Read the intro to 211 for some of the concerns -- this PEP tries to make the addition palatable by adding exactly *one* new operator.)
So! Introductory books don't have to discuss these additional operators. I don't have to know about XML and socket modules to start using Python effectively, nor do I have to know about 'zip' or list comprehensions. These additions decrease the code size and increase efficiency, but don't really add any new expressive power that can't already be done by a 'for' loop.
I'll try to convince myself that this suggestion is crazy and not bother you with this issue for awhile.
Happy holidays nevertheless. :-) --Guido van Rossum (home page: http://www.python.org/~guido/)
[Paul Barrett]
... Can someone provide an example in mathematics where comparison operators are used in a non-boolean, ie. rich comparison, context. If so, this might shut me up!
By my informal accounting, over the years there have been more requests for three-outcome comparison operators than for elementwise ones, although the three-outcome lobby isn't organized so is less visible. It's a natural request for anyone working with partial orderings (a < b -> one of {yes, no, unordered}). Another large group of requests comes from people working with variants of fuzzy logic, where it's desired that the comparison operators be definable to return floats (intuitively corresponding to the probability that the stated relation "is true"). Another desire comes from the symbolic math camp, which would like to be able to-- as is possible for "+", "*", etc --define "<" so that e.g. "x < y" return an object capturing that somebody *asked* for "x < y"; they're not interested in numeric or Boolean results so much as symbolic expressions. "<" is used for all these things in the literature too. Whatever. "<" and friends are just collections of pixels. Add 300 new operator symbols, and people will want to redefine all of them at will too. draw-a-line-in-the-sand-and-the-wind-blows-it-away-ly y'rs - tim
[Paul Barrett]
... Can someone provide an example in mathematics where comparison operators are used in a non-boolean, ie. rich comparison, context. If so, this might shut me up!
Not exactly mathematical, but some day I'd like to create a database access module which lets you say things like mydb = OpenDB("inventory") parts = mydb.parts tuples = mydb.retrieve(parts.name, parts.number).where(parts.quantity >= 42) Of course, to really make this work I need to be able to overload "and" and "or" as well, but that's a whole 'nother PEP... Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Not exactly mathematical, but some day I'd like to create a database access module which lets you say things like
mydb = OpenDB("inventory") parts = mydb.parts tuples = mydb.retrieve(parts.name, parts.number).where(parts.quantity >= 42)
Of course, to really make this work I need to be able to overload "and" and "or" as well, but that's a whole 'nother PEP...
Believe it or not, in 1998 we already had a suggestion for overloading
these too. This is hinted at in David Ascher's proposal (the Appendix
of PEP 208) where objects could define __boolean_and__ to overload
x
The problem I have with this is that the code to evaluate g() has to be generated twice!
I have an idea how to fix that. There need to be two methods, __boolean_and_1__ and __boolean_and_2__. The first operand is evaluated and passed to __boolean_and_1__. If it returns a result, that becomes the result of the expression, and the second operand is short-circuited. If __boolean_and_1__ raises a NeedOtherOperand exception (or there is no __boolean_and_1__ method), the second operand is evaluated, and both operands are passed to __boolean_and_2__. The bytecode would look something like <evaluate first operand> BOOLEAN_AND_1 label <evaluate second operand> BOOLEAN_AND_2 label: ... I'll make a PEP out of this one day if I get enthusiastic enough. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
participants (4)
-
Greg Ewing
-
Guido van Rossum
-
Paul Barrett
-
Tim Peters