[Steve R. Hastings]
> So, Python 2.5 will have new any() and all() functions.
> http://www.python.org/dev/peps/pep-0356/
>
>
> any(seq) returns True if any value in seq evaluates true, False otherwise.
>
> all(seq) returns True if all values in seq evaluate true, False otherwise.
>
> I have a question: what should these functions return when seq is an empty
> list?

Here, from the current development trunk, is what they _do_ return:

Python 2.5a0 (trunk:43410M, Mar 28 2006, 16:42:49) ...
Type "help", "copyright", "credits" or "license" for more information.
>>> any([])
False
>>> all([])
True

> Here is Guido's original article where he suggested any() and all():
> http://www.artima.com/weblogs/viewpost.jsp?thread=98196
>
> He offered this sample code for the semantics of any() and all():
>
>
>
> def any(S):
>     for x in S:
>         if x:
>             return True
>     return False
>
> def all(S):
>     for x in S:
>         if not x:
>             return False
>     return True
>
> ...
>|
> I'm completely on board with the semantics for any().  But all() bothers
> me.  If all() receives an empty list, it will return True,

Yes.

> and I don't like that.

Tough ;-)

> To me, all() should be a more restrictive function than any(),
> and it bothers me to see a case where any() returns False but all()
> returns True.

There are deeper principles at work:  so that endcases work out as
smoothly as possible, a "reduction" function applied to an empty
collection always arranges to return the identity element for the
reduction operation.  This is the reason that sum([]) returns 0, for
example:  0 is the identity element for addition, meaning that x+0=x
for all x.

Other useful identities follow from this, and from the associativity
of most reduction operations.  For example, sum(seq) = sum(seq[:i]) +
sum(seq[i:]) for any i >= 0, even if i is such that one (or both!) of
the slices on the right-hand side is empty.  That wouldn't be true if
sum([]) were not 0, and arranging to make it true saves programmers
from having to deal with some otherwise special cases.

The reduction operation for any() is logical-or, and False is the
identity element for logical-or:   x logical-or False = x for all
Boolean x.

Likewise the reduction operation for all() is logical-and, and True is
the identity element for that:  x logical-and True = x for all Boolean
x.

Examples of other useful identities that follow from picking the
identity elements in the empty case, which hold even if `seq` is
empty:

    any(seq) = not all(not x for x in seq)
    all(seq) = not any(not x for x in seq)

> In the all() example, if there *are* no values in S, then none of the
> values can be != 0, and IMHO all() should return False.

That would break everything mentioned above.  Think of it another way:
 if all(seq) is false, shouldn't it be the case that you can point to
a specific element in seq that is false?  After all (pun intended
;-)), if it's not the case that all x in seq are true, it must be the
case that some x in seq is false.  But if seq is empty, there is no x
in seq that's either true or false, and in particular there's no x in
seq that's false.  Since we can't exhibit an x in seq such that x is
false, saying that all(seq) is false would be very surprising to you
on some other day ;-)

> Therefore, I propose that all() should work as if it were written this way:
>
> def all(S):
>     ret_val = False
>
>     for x in S:
>         ret_val = True
>         if not x:
>             return False
>
>     return ret_val
>
>
> Comments?

That won't happen, for three reasons:  several were given above; this
is also the convention used for universal and existential quantifiers
applied to empty sets in mathematical logic (and for much the same
reasons there); and it matches prior art in the ABC language (which is
one of Python's predecessors, and which had direct syntactic support
for universal and existential quantifiers in Boolean expressions).
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to