LoginSignup
1
0

More than 5 years have passed since last update.

Array#include?で引数にnilを指定した際にtrueになる条件

Posted at

何が言いたいかわかりにくいが、要は下記ケースだとtrueが返るという話。

[1] pry(main)> [1,2,nil].include?(nil)
=> true

nil を含む配列に対して nil を渡すと true が返されます。

冷静に見れば当たり前な気がしますが、何となくnilの比較はfalseが返る思い込みみたいなのがあるというか、ちょっとモヤってしたので調べました。

調べたって言っても、ソースを見たらすぐわかりましたが。

[2] pry(main)> show-source Array#include?
rb_ary_includes(VALUE ary, VALUE item)
{
    long i;
    VALUE e;

    for (i=0; i<RARRAY_LEN(ary); i++) {
        e = RARRAY_AREF(ary, i);
        if (rb_equal(e, item)) {
            return Qtrue;
        }
    }
    return Qfalse;
}

rb_equal が何かというと == メソッドの事で、配列の中に nil が含まれるということは、ループの中で nil == nil が評価されることで true が返されるという事になります。
https://docs.ruby-lang.org/ja/latest/function/rb_equal.html

[3] pry(main)> nil == nil
=> true

Activesupport の in? メソッドも include? を呼んでいるのでこちらの条件が当てはまります。

  # activesupport/lib/active_support/core_ext/object/inclusion.rb
  def in?(another_object)
    another_object.include?(self)
  rescue NoMethodError
    raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
  end

実際に今回の内容を調べるきっかけになったのは、以下みたいな条件で hoge=nil なのに先に進んでしまいエラーになった事からでした。

# hoge => nil
# piyos => [1,2,nil]
return unless hoge.in?(piyos)  # => trueが返るのでreturnされない

まぁそもそも hoge に対して nil チェックしたり、 piyos に対して compact を当てろって話ですけどね。。。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0