Why does .all? return true on an empty array?

2020-02-10 01:56发布

Using Ruby I want to evaluate all items in an array, and return true if they all pass a conditional test.

I can do this using e.g. array.all? { |value| value == 2 }

So:

> array=[2,2]
> array.all? { |value| value == 2 }
=> true
> array=[2,3]
> array.all? { |value| value == 2 }
=> false

Great!

But, why does an empty array pass this test?

> array=[]
> array.all? { |value| value == 2 }
=> true

Shouldn't this return false?

And if I need it to return false, how should I modify the method?

标签: ruby
10条回答
Evening l夕情丶
2楼-- · 2020-02-10 02:00

As Amit Kumar Gupta writes, it is the standard interpretation of universal quantification. I have no idea why you expect it to be false. Here, you can see it should be true by inference.


Universal quantification is equivalent to conjunction, thus ("<=>" means equivalent):

"for all x in [a, b, c], P(x)" <=> "P(a) and P(b) and P(c)"

Notice that any proposition is equivalent to the conjunction of true and itself, so:

"for all x in [a, b, c], P(x)" <=> "true and P(a) and P(b) and P(c)"

If you lessen the elements in the set to two, you get:

"for all x in [a, b], P(x)" <=> "true and P(a) and P(b)"

and further to one element:

"for all x in [a], P(x)" <=> "true and P(a)"

Now, what happens with the empty set? Naturally,

"for all x in [], P(x)" <=> "true"


By noticing that existential quantification is equivalent to disjunction, you can also see that you should expect false with existential quantification over an empty set.

查看更多
狗以群分
3楼-- · 2020-02-10 02:03

Since there is no item in the array that FAILS that test, it returns true. So just use somehting like:

array.size > 0 and array.all? { |value| value == 2}

Or something like that.

查看更多
别忘想泡老子
4楼-- · 2020-02-10 02:08

The source of all? method says that it uses static variable(which is initially set to true) and then performs the AND operation between the static variable value and the result of the iteration finally returns this static variable as a result.

as the array is Empty ruby will never iterate on this empty array and as a result of this all? method will return the static variable which was set to true.

查看更多
ゆ 、 Hurt°
5楼-- · 2020-02-10 02:10

This is a vacuous truth. It's the standard interpretation of a universal quantification, i.e. a

collection.all? { |x| some_predicate(x) }

over an empty collection, but it's known to strike people as counter-intuitive when they first see it in a formal setting. One nice way to think about why this is the preferred semantics is to think about how you would implement all?.

To make your test require that the array is non-empty, just do

array.any? && array.all? { |x| x == 2 }

Note that array.any? is fast no matter how large the array, whereas array.all? { |x| x == 2 } can be slow, depending on how big array is and how rare 2 is in it. So put the array.any? first.

Also note, there are degenerate cases where this won't work, for instance if array is [nil] or [false]. If cases like this might come up, replace array.any? with array.any? { true }.

查看更多
可以哭但决不认输i
6楼-- · 2020-02-10 02:11

The documentation says : "The method returns true if the block never returns false or nil.." In the case of an empty array the block never executes and hence the method will always return true. As far as returning false is concerned you'll have to arr.empty?

查看更多
霸刀☆藐视天下
7楼-- · 2020-02-10 02:15

There is no item in that array that doesn't pass the test. I think you may need to throw in a test for array length.

查看更多
登录 后发表回答