Enumerable#all? が罠っぽかった

Rubyの話です。
お仕事をしていたら「罠だよなぁ」といっている同僚がいたので調べてみたメモです。

f:id:tanaken0515:20181208132928p:plain

Enumerable#all?

instance method Enumerable#all? (Ruby 2.5.0)

すべての要素が真である場合に true を返します。 偽である要素があれば、ただちに false を返します。 ブロックを伴う場合は、各要素に対してブロックを評価し、すべての結果 が真である場合に true を返します。ブロックが偽を返した時点で、 ただちに false を返します。

例えばこう↓書く。全部3の倍数だったらtrue、3の倍数じゃないやつが1つでもあったらfalseみたいな。

irb(main):001:0> [3, 6, 9].all? {|item| item % 3 == 0}
=> true
irb(main):002:0> [3, 6, 8].all? {|item| item % 3 == 0}
=> false

罠っぽさ

Enumerable#all?レシーバが空配列のときtrueを返します

irb(main):003:0> [].all? {|item| item % 3 == 0}
=> true

なので例えば次のようなメソッドがあるとして

def all_multiple_of_3?(items)
  items.all? {|item| item % 3 == 0}
end

下のような感じになります。

irb(main):001:0> all_multiple_of_3?([3, 6, 9])
=> true
irb(main):002:0> all_multiple_of_3?([3, 6, 8])
=> false
irb(main):003:0> all_multiple_of_3?([])
=> true

👵「[] は全部3の倍数なのかい?」
👦『 そうだよ!

罠っぽい。

何となくですが

👦『 3の倍数じゃなかった奴はいなかったよ!
(最初から誰もいなかった(=空配列だった)んだからそうだよね)

みたいなことなのかなと思いました。

罠っぽさパトロール 👮‍♂️

all? (Enumerable) - Rubyリファレンス には「関連項目」に次の3つがあったので、念のため罠っぽくないかパトロールしました。

  • any? : どれか○○かを調べる。
  • none? : すべて○○でないかを調べる。Ruby 1.8.7
  • one? : 1つだけ○○かを調べる。Ruby 1.8.7
irb(main):001:0> [].any?
=> false
irb(main):002:0> [].none?
=> true
irb(main):003:0> [].one?
=> false

罠っぽくありませんでした。よかった。

まとめ

👩‍🏫『Enumerable#all? はレシーバが空配列のときtrueを返すから気をつけましょう』

ではまた。