Reason for "all" and "any" result on empty lists
Solution 1:
How about some analogies...
You have a sock drawer, but it is currently empty. Does it contain any black sock? No - you don't have any socks at all so you certainly don't have a black one. Clearly any([])
must return false - if it returned true this would be counter-intuitive.
The case for all([])
is slightly more difficult. See the Wikipedia article on vacuous truth. Another analogy: If there are no people in a room then everyone in that room can speak French.
Mathematically all([])
can be written:
where the set A is empty.
There is considerable debate about whether vacuous statements should be considered true or not, but from a logical viewpoint it makes the most sense:
The main argument that all vacuously true statements are true is as follows: As explained in the article on logical conditionals, the axioms of propositional logic entail that if P is false, then P => Q is true. That is, if we accept those axioms, we must accept that vacuously true statements are indeed true.
Also from the article:
There seems to be no direct reason to pick true; it’s just that things blow up in our face if we don’t.
Defining a "vacuously true" statement to return false in Python would violate the principle of least astonishment.
Solution 2:
One property of any
is its recursive definition
any([x,y,z,...]) == (x or any([y,z,...]))
That means
x == any([x]) == (x or any([]))
The equality is correct for any x
if and only if any([])
is defined to be False. Similar for all
.
Solution 3:
I believe all([])==True
is generally harder to grasp, so here are a collection of examples where I think that behaviour is obviously correct:
- A movie is suitable for the hard of hearing if all the dialog in the film is captioned. A movie without dialog is still suitable for the hard of hearing.
- A windowless room is dark when all the lights inside are turned off. When there are no lights inside, it is dark.
- You can pass through airport security when all your liquids are contained in 100ml bottles. If you have no liquids you can still pass through security.
- You can fit a soft bag through a narrow slot if all the items in the bag are narrower than the slot. If the bag is empty, it still fits through the slot.
- A task is ready to start when all its prerequisites have been met. If a task has no prerequisites, it's ready to start.
Solution 4:
I think of them as being implemented this way
def all(seq):
for item in seq:
if not item:
return False
return True
def any(seq):
for item in seq:
if item:
return True
return False
not sure they are implemented that way though
Solution 5:
Perl 6 also takes the position that all()
and any()
on empty lists should serve as sane base-cases for their respective reduction operators, and therefore all()
is true and any()
is false.
That is to say, all(a, b, c)
is equivalent to [&] a, b, c
, which is equivalent to a & b & c
(reduction on the "junctive and" operator, but you can ignore junctions and consider it a logical and for this post), and any(a, b, c)
is equivalent to [|] a, b, c
, which is equivalent to a | b | c
(reduction on the "junctive or" operator -- again, you can pretend it's the same as logical or without missing anything).
Any operator which can have reduction applied to it needs to have a defined behavior when reducing 0 terms, and usually this is done by having a natural identity element -- for instance, [+]()
(reduction of addition across zero terms) is 0 because 0 is the additive identity; adding zero to any expression leaves it unchanged. [*]()
is likewise 1 because 1 is the multiplicative identity. We've already said that all
is equivalent to [&]
and any
is equivalent to [|]
-- well, truth is the and-identity, and falsity is the or-identity -- x and True is x, and x or False is x. This makes it inevitable that all()
should be true and any()
should be false.
To put it in an entirely different (but practical) perspective, any
is a latch that starts off false and becomes true whenever it sees something true; all
is a latch that starts off true and becomes false whenever it sees something false. Giving them no arguments means giving them no chance to change state, so you're simply asking them what their "default" state is. :)