
PEP 326 reads:
Users of Python have had the constant None, which represents a lack of value, for quite some time (possibly from the beginning, this is unknown to the author at the current time). The author believes that ``All`` should be introduced in order to represent a functionally infinite value, with similar behavior corresponding to None.
[Gerrit Holl]
I think the described behavious of None is one of the rarest uses of None. Actually, I didn't even know of the existence of this behaviour. I think None is mainly used to show the absence of *anything*: when a function does not return a value, it return None, when some variable does not have a value yet, it may be set to None, when a HTTP connection is not opened yet, it's socket is None, etc.
As previously offered by Tim Peters: http://mail.python.org/pipermail/python-dev/2003-December/041374.html The behavior of None being smaller than anything else was a concious decision. The use of All doesn't change the behavior of None. How people end up using All in their algorithms is up to them. Does the Python language restrict the usage of None? Of course not. Just as a function can return None (as a signal to the caller), a function can now return All as a signal to the caller. Further uses of All will be left as an exercise to whomever wants to use it.
Introducing an ``All`` built-in that works as described does not take much effort. A sample Python implementation is included.
I don't think it is used very often. ``All`` is not a very straightforward name as well. The implementation is created very quickly: it can be done much simpler than you did, although it won't be called All then:
class Infinity(object): def __cmp__(self, other): return 1
The problem with your ``Infinity`` implementation is that it compares greater than itself and doesn't follow the standard python object convention of: a = obj;b = eval(repr(obj));a == b
class Infinity(object): ... def __cmp__(self, other): ... return 1 ... I = Infinity() I == I 0 I is I 1 I <__main__.Infinity object at 0x007A5720>
The implementation that I offer in the PEP fixes the problem with your ``Infinity`` implementation.
This is usable everywhere you describe. Because ``All`` is not a very straightforward name, I think the namespace cluttering is worse than the advantages. To convince me, I think you'll need to come up with a better name. It isn't ``All`` really, because that makes sence only with container types, it isn't ``Infinity`` because that makes sense only with numbers (strings?), so this is the biggest problem of your proposal.
All is a resonably lengthed name for the concept of 'bigger than anything'. This was independantly offered by two developers on the python-dev mailing list: Tim Peters: http://mail.python.org/pipermail/python-dev/2003-December/041337.html David LeBlanc http://mail.python.org/pipermail/python-dev/2003-December/041386.html It also has a similar naming semantic of None. What is the opposite of None (conceptually)? All of course. - Josiah

At 12:00 PM 1/4/04 -0800, Josiah Carlson wrote:
Further uses of All will be left as an exercise to whomever wants to use it.
Um, then why don't those people just write their own 'All'? It's not like they all need to be using the same definition of 'All', so why put it in Python? The "Motivation" section of PEP 326 does not answer this question. Although it claims "hundreds of algorithms", it demonstrates only *one*: finding the minimum of a sequence. The example shows three versions of finding a minimum of a sequence, to show that it's easier with 'All'. But that's a straw man argument: the *easiest* way to get the desired behavior is just to use 'min(seq)' and not write any new functions at all! So, essentially, the "Motivation" section might as well not be in the PEP, because it provides no actual motivation at all. You need to find a better algorithm to cover. And don't bother using "find the pair x,y from a sequence of pairs where 'x' is the lowest item" as a substitute, because again the answer is 'min(seq)'. And even if you say, "yes but we don't want 'y' to be compared", there's always: def min_key(pairs): minX, chosenY = pairs[0] for x,y in pairs[1:] if x<minX: minX, chosenY = x,y return minX, chosenY or, if you prefer using iterators to slicing: def min_key(pairs): pairs = iter(pairs) minX, chosenY = pairs.next() for x,y in pairs if x<minX: minX, chosenY = x,y return minX, chosenY So, please pick some examples that aren't based on finding minimums, and that also illustrate why it's important that Python itself include this concept. Can you show why it's a bad thing for people to implement their own infinity-like type(s)? In what areas does the standard library show a need for such an object? And so on. Without more motivation for the proposal, you're likely to see continued opposition to the PEP.

Further uses of All will be left as an exercise to whomever wants to use it.
Um, then why don't those people just write their own 'All'? It's not like they all need to be using the same definition of 'All', so why put it in Python?
Just because something is simple in idea and implementation, doesn't mean that it shouldn't be included with Python. The entire itertools module is filled with very useful functions that are simple in idea and implementation. The introduction of All into Python would offer users the opportunity to use an always-compatible implementation of All, without the arbitrariness of argument placement during comparisons:
class _AllType(object): ... def __cmp__(self, other): ... if isinstance(other, self.__class__): ... return 0 ... return 1 ... def __repr__(self): ... return 'All' ... class _AllType2(object): ... def __cmp__(self, other): ... if isinstance(other, self.__class__): ... return 0 ... return 1 ... def __repr__(self): ... return 'All2' ... All = _AllType() All2 = _AllType2() All > All2 1 All2 > All 1
The "Motivation" section of PEP 326 does not answer this question. Although it claims "hundreds of algorithms", it demonstrates only *one*: finding the minimum of a sequence.
I should have probably made it more explicit. The most visible change when using All, in cases where a logical infinity was needed, is the removal of some "or (cur is None)" blobs. The next most visible change is the increase in understandability of some algorithms who require an infinity initialization.
The example shows three versions of finding a minimum of a sequence, to show that it's easier with 'All'. But that's a straw man argument: the *easiest* way to get the desired behavior is just to use 'min(seq)' and not write any new functions at all!
So, essentially, the "Motivation" section might as well not be in the PEP, because it provides no actual motivation at all. You need to find a better algorithm to cover.
I offered the finding the minimum code in order to offer an easily understood algorithm that is simplified by All's introduction. If you would like, I'll put together some code that solves various graph algorithm problems, use 'All', and are simplified because of it. I did not post any in the PEP because I believed that the implications of All were straightforward.
And don't bother using "find the pair x,y from a sequence of pairs where 'x' is the lowest item" as a substitute, because again the answer is 'min(seq)'. And even if you say, "yes but we don't want 'y' to be compared", there's always:
That is quite unfriendly and insulting. Call me an idiot next time, it'll be straighter to the point. As Raymond Hettinger points out, Alex Martelli has a suggestion to allow the "key" keyword to min and max that could do everything required with with itemgetter. Or even: def m(a,b): if a[0] < b[0]: return a return b reduce(m, seq) "All" isn't about how many different ways there are to find the minimum of a sequence. "All" is about having a useful and consistant constant. Thank you for your input, - Josiah

* Josiah Carlson <jcarlson@uci.edu> [2004-01-04 16:28]:
I should have probably made it more explicit. The most visible change when using All, in cases where a logical infinity was needed, is the removal of some "or (cur is None)" blobs. The next most visible change is the increase in understandability of some algorithms who require an infinity initialization.
Hi Josiah- Others have commented on the suitability of your name "All". I wanted to point out that in the paragraph above, you resort to calling it "infinity" when talking about it. I think this is telling as to the readability of the name "All". If it doesn't make sense to use the name in discussion, what makes you think it will make sense in a program? Since we're really talking about "infinity" here (its only use is in comparison), why not just call it that? I've heard you make two points for the name "All" -- that it's easier to type than "Infinity", and that it's (in some way) analagous to "None". To me, one of the strengths of python is its emphasis on readability, even (sometimes) at the expense of ease of typing. Also, "All" only has an analogue to one of the uses of None (which, as others have mentioned, is not the primary use). So, to get around the resistance to this because of the name (Guido begged for a better name than "Some", but I think "All" is just as bad), why not just change it to "Infinity"? If the asymmetry of None and Infinity bothers you, I would suggest also proposing a NegativeInfinity, and we could consider eventually deprecating comparisons on None. -John P.S. - Hello, py-dev'ers. This is my first post, but I've been lurking for quite a while. Thank you all for creating a great language! I'll introduce myself more completely within a few weeks, when I find a way to begin contributing.

At 04:29 PM 1/4/04 -0800, Josiah Carlson wrote:
Just because something is simple in idea and implementation, doesn't mean that it shouldn't be included with Python. The entire itertools module is filled with very useful functions that are simple in idea and implementation.
And they're not built-ins, either.
The introduction of All into Python would offer users the opportunity to use an always-compatible implementation of All, without the arbitrariness of argument placement during comparisons:
class _AllType(object): ... def __cmp__(self, other): ... if isinstance(other, self.__class__): ... return 0 ... return 1 ... def __repr__(self): ... return 'All' ... class _AllType2(object): ... def __cmp__(self, other): ... if isinstance(other, self.__class__): ... return 0 ... return 1 ... def __repr__(self): ... return 'All2' ... All = _AllType() All2 = _AllType2() All > All2 1 All2 > All 1
Can you show how/why this is a problem, or is likely to be a problem? The point of not putting simple things into the standard library isn't whether they're simple, it's whether enough people (or standard library modules) need to do it, and if there are relatively few people who need to do it, and they *can* do it, why not let them do it themselves? The examples you keep presenting aren't motivating in themselves. If I agreed with you that it was a widely-needed and useful object, the content of your PEP (apart from the Motivation section) would be helpful and informative. But the PEP provides no real motivation, except a repeated assertion that some set of algorithms would be clearer with its use.
The "Motivation" section of PEP 326 does not answer this question. Although it claims "hundreds of algorithms", it demonstrates only *one*: finding the minimum of a sequence.
I should have probably made it more explicit. The most visible change when using All, in cases where a logical infinity was needed, is the removal of some "or (cur is None)" blobs.
Perhaps I should've made my point more explicit. I find it clearer and more efficient for "find a minimum" to take a value from the items under consideration, than to construct an artificial starting point. That's the only algorithm you presented, so it's the only one I could reasonably comment on.
The next most visible change is the increase in understandability of some algorithms who require an infinity initialization.
Please illustrate some that would be commonly used, and not better off as say, part of a graph algorithms library. (In the latter case, such a library could certainly provide its own logical infinity implementation, specifically suited to the use cases involved.)
I offered the finding the minimum code in order to offer an easily understood algorithm that is simplified by All's introduction.
But it's not a *motivating* example, because the problem you presented is trivially solved using min(), slicing, or iterators.
If you would like, I'll put together some code that solves various graph algorithm problems, use 'All', and are simplified because of it. I did not post any in the PEP because I believed that the implications of All were straightforward.
The implications are straightforward enough. The motivation for a builtin is not. Based on the discussion so far, it seems to me that this is something that belongs in e.g. the Python Cookbook, or part of a graph processing library if there are lots of graph algorithms that need it. So far, you haven't mentioned anything but graph algorithms; are there other common applications of this object? What are they? Without *concrete* use cases, it's impossible to validate the design. Over the course of these threads, you've asserted various invariants you expect All to meet. These invariants are not documented in the PEP (except implicitly in the implementation), nor are their reasoning explained. But, since the only use case you've given is reimplementing 'min', how can anyone say if the invariants you've asserted are the correct ones for the intended uses? For example, why must All compare equal to other instances of its type? It's certainly not necessary for the reimplementing 'min'. Should it even be allowable to create more than one instance of the type? How can we know the answers to these questions without actual use cases? We can only answer YAGNI, and wait for libraries to pop up where people actually use a logical infinity object. When they do, we'll either find that: 1) the invariants they use are the same, possibly justifying an addition to Python, or 2) the invariants they use are necessarily different, meaning there's no reason to pick one arbitrarily.
"All" isn't about how many different ways there are to find the minimum of a sequence. "All" is about having a useful and consistant constant.
Useful to whom, for what? That is the question that isn't even touched on in your PEP, apart from the "minimum of a sequence" example. By the way, with regards to your references section, it might be a good idea to include this one: http://mail.python.org/pipermail/python-dev/2003-December/041332.html whose last paragraph goes to the point I'm making about choosing invariants based on actual use cases.
participants (3)
-
john@hazen.net
-
Josiah Carlson
-
Phillip J. Eby