From ce5b583ec526cc53a44a7f0910f21256069e323d Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 4 Dec 2000 20:32:13 +0000 Subject: [PATCH] Checking in some text. Most of this is simply an Appendix repeating what David Ascher said in 1998 (before the starship bites the dust again). --- pep-0207.txt | 323 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 322 insertions(+), 1 deletion(-) diff --git a/pep-0207.txt b/pep-0207.txt index b03b15275..a98f84615 100644 --- a/pep-0207.txt +++ b/pep-0207.txt @@ -1,11 +1,332 @@ PEP: 207 Title: Rich Comparisions Version: $Revision$ -Author: mal@lemburg.com (Marc-Andre Lemburg), guido@python.org (Guido van Rossum) +Author: guido@python.org (Guido van Rossum), mal@lemburg.com (Marc-Andre Lemburg) Python-Version: 2.1 Status: Incomplete +Abstract + + This PEP proposes several new features for comparisons: + + - Allow separately overloading of <, >, <=, >=, ==, !=, both in + classes and in C extensions. + + - Allow any of those overloaded operators to return something else + besides a Boolean result. + + +Motivation + + The main motivation comes from NumPy, whose users agree that A", ">=", "==", "!=", "<>" (the last two have the same + meaning). When called with one of these strings as the third + argument, cmp() can return any Python object. Otherwise, it can + only return -1, 0 or 1 as before. + +Chained Comparisons + + Problem + + It would be nice to allow objects for which the comparison returns + something other than -1, 0, or 1 to be used in chained + comparisons, such as: + + x < y < z + + Currently, this is interpreted by Python as: + + temp1 = x < y + if temp1: + return y < z + else: + return temp1 + + Note that this requires testing the truth value of the result of + comparisons, with potential "shortcutting" of the right-side + comparison testings. In other words, the truth-value of the result + of the result of the comparison determines the result of a chained + operation. This is problematic in the case of arrays, since if x, + y and z are three arrays, then the user expects: + + x < y < z + + to be an array of 0's and 1's where 1's are in the locations + corresponding to the elements of y which are between the + corresponding elements in x and z. In other words, the right-hand + side must be evaluated regardless of the result of x < y, which is + incompatible with the mechanism currently in use by the parser. + + Solution + + Guido mentioned that one possible way out would be to change the + code generated by chained comparisons to allow arrays to be + chained-compared intelligently. What follows is a mixture of his + idea and my suggestions. The code generated for x < y < z would be + equivalent to: + + temp1 = x < y + if temp1: + temp2 = y < z + return boolean_combine(temp1, temp2) + else: + return temp1 + + where boolean_combine is a new function which does something like + the following: + + def boolean_combine(a, b): + if hasattr(a, '__boolean_and__') or \ + hasattr(b, '__boolean_and__'): + try: + return a.__boolean_and__(b) + except: + return b.__boolean_and__(a) + else: # standard behavior + if a: + return b + else: + return 0 + + where the __boolean_and__ special method is implemented for + C-level types by another value of the third argument to the + richcmp function. This method would perform a boolean comparison + of the arrays (currently implemented in the umath module as the + logical_and ufunc). + + Thus, objects returned by rich comparisons should always test + true, but should define another special method which creates + boolean combinations of them and their argument. + + This solution has the advantage of allowing chained comparisons to + work for arrays, but the disadvantage that it requires comparison + arrays to always return true (in an ideal world, I'd have them + always raise an exception on truth testing, since the meaning of + testing "if a>b:" is massively ambiguous. + + The inlining already present which deals with integer comparisons + would still apply, resulting in no performance cost for the most + common cases. + Local Variables: mode: indented-text