Behavior of all() and any() on empty vectors

This caught me by surprise:

``````julia> any(x->true, [])
false

julia> all(x->true, [])
true

julia> any(x->false, [])
false

julia> all(x->false, [])
true
``````

This seems like a bug - I think that `all` should never be true when `any` is false. But I’m guessing there’s a principled reason for this. Can anyone explain it to me?

1 Like

The key is this that `any` returns `true` if there are any `true` elements. No elements means that there can’t be any `true` elements, thus it’s always `false`. Similarly `all` returns `false` if there are any `false` elements. No elements means there can’t be any `false` elements, thus it’s always `true`. Both short-circuit upon finding the first “exceptional” value when it knows the result.

Practically, I really like the `any` behavior but — while I see the motivation and symmetry — I often want `all([])` to be `false`. I often just have to remember to add in the fact that I want `!isempty` to my predicates that include `all`.

4 Likes

Yeah, this seems more sensible to me. Logically, it seems like `all(f, x) && !any(f, x)` should never be true.

This behavior agrees with Matlab, at least.

Yeah, there are two ways to think about these operations. There’s the way we (and Matlab and Numpy) operate:

• `any`: `true` if contains a `true`, `false` otherwise
• `all`: `false` if contains a `false`, `true` otherwise

They could also potentially be defined by leading with the converse in an alternate universe′:

• `any′`: `false` if only contains `false`s, `true` otherwise. Thus: `any′([]) == true`
• `all′`: `true` if only contains `true`s, `false` otherwise. Thus: `all′([]) == false`

I think colloquially, we tend to think about how things are true (that is, leading with the `true` if…; the `any` and `all′` definitions), but if the “all” operation is going to short-circuit like any does, then it’s sensible to be defined as `all`. The docstring could probably be clearer in this regard.

1 Like

With this definition, it’s not obvious to me that `any'([]) == true`… In a sense, `Bool[]` contains only `false`, as it doesn’t contain any `true`s and can’t contain something else than `true` or `false`.

I don’t know if the current definition is “principled”, but it’s consistent with `sum` and `prod`: `any(a)` is equivalent to `sum(a) % Bool` (think a sum in the 2-element field `GF(2)`), and `all(a)` is equivalent to `prod(a)`. An empty sum is usually defined to be the addition identity, i.e. 0 or `false` in our case, whereas an empty product is defined to be the mutliplication identity, i.e. 1 or `true`.

1 Like

I would say `Bool[]` does not contain a single `false`. Perhaps there’s better verbiage to be used than “only contains”, but it’s tricky to define these without using the words (implicitly or explicitly) themselves. I think you’re implicitly using the "`true` if" definition here.

Absolutely! It’s because I can’t really decide if an empty collection contains “only false”… it’s not a clear concept, so for me the closest definition to disambiguate this corner case is the “true if”, while for you it’s the “not empty and contains only false”

1 Like