Ruby gotcha? [].all? always returns true

Something in caught me out today. I wanted to test that the contents
of the array where all instances of particular class, and if not, do
stuff. The example isn’t exactly what my code did, but it illustrates
my point:

if not my_arr.all? { |i| i.is_a(Integer) }

Do stuff

end

I expecting it to ‘do stuff’, however I found it was not. I discovered
that ‘my_arr’ was empty, which was not a surprise, but what did
surprise me was that all? called on an empty array appears to always
return true.

I don’t know about you, but these seems counter-intuitive to me. Does
anyone agree or disagree?

I’ve now resorted to any? instead, like as follows:

if not my_arr.any? { |i| not i.is_a(Integer) }

Do stuff

end

As far as it seems [].any? always returns false. The code should also
be slightly more efficient as it doesn’t always have to check every
item of the array, not that I expect it to get very big.

On 4/26/07, Dan Stevens (IAmAI) [email protected] wrote:

On Apr 27, 2007, at 12:55 AM, Dan Stevens (IAmAI) wrote:

that ‘my_arr’ was empty, which was not a surprise, but what did
surprise me was that all? called on an empty array appears to always
return true.

I don’t know about you, but these seems counter-intuitive to me. Does
anyone agree or disagree?

Yeah, it is suprising at first sight but that’s standard semantics in
math.

A for all statement like that holds always for the empty set because
otherwise you’d need to show an element of the empty set (impossible)
for which the test is false. The reason is

not for all x in S P(x)

is logically equivalent to

there exists x in S such that not P(x)

This is a corner case, note that it does not depend on P.

– fxn

“Dan Stevens (IAmAI)” [email protected] writes:

anyone agree or disagree?
It seems perfectly intuitive to me.

There’s a local law that states that all dogs must wear leashes when
not confined behind a fence. We are in full compliance with that law,
even though our front yard has no fence and we own no leashes - this
is because we have no dogs.

I’ve now resorted to any? instead, like as follows:

if not my_arr.any? { |i| not i.is_a(Integer) }

Do stuff

end

As far as it seems [].any? always returns false. The code should also
be slightly more efficient as it doesn’t always have to check every
item of the array, not that I expect it to get very big.

Actually, all? has the same efficiency characteristics. That is, the
instant it finds something false, it returns false.

On Apr 27, 2007, at 2:21 PM, Daniel M. wrote:

return true.

I don’t know about you, but these seems counter-intuitive to me. Does
anyone agree or disagree?

It seems perfectly intuitive to me.

There’s a local law that states that all dogs must wear leashes when
not confined behind a fence. We are in full compliance with that law,
even though our front yard has no fence and we own no leashes - this
is because we have no dogs.

A good explanation.

Let me elaborate it a bit more. The parallelism there goes: "you are
within the law if all your dogs satisfy ". Can I say that
"all my dogs satisfy " is true if I have no dog? Why? In
what sense can I say something holds in an empty collection?

To see why the response is yes, I think we need to go a little step
further: The point is that a policeman should prove one of your dogs
does not satisfy to say you’ve break the law. It’s
because that’s impossible that you are within the law as far as that
law concerns. Therefore, since you are either within or outside the
law, "all your dogs satisfy " necessarily holds.

That’s the formal equivalence I mentioned earlier (what makes
logicians define for all and there exists that way is our intuitive
reasoning about dogs and laws, formal logic as such does not justify
per se that’s OK that way.)

– fxn