Пользовательский оператор == не используется при сравнении объекта с самим собой с помощью #include? - PullRequest
0 голосов
/ 25 января 2019

документы для Array#include? указывают, что включение проверяется с помощью оператора ==.Я проверяю это в случае сравнения объекта с самим собой, используя пользовательский определенный ==:

class Foo
  def ==(other)
    false
  end
end

f = Foo.new
f == f # => false 

В таком случае описание документа не соответствует действительности, и другой механизм имеет приоритет:

[f].include?(f) # => true

Что это за механизм и где он определен?

Ответы [ 2 ]

0 голосов
/ 25 января 2019

чтение исходного кода

               VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
    long i;
    VALUE e;

    for (i=0; i<RARRAY_LEN(ary); i++) {
        e = RARRAY_AREF(ary, i);
        switch (rb_equal_opt(e, item)) {
          case Qundef:
            if (rb_equal(e, item)) return Qtrue;
            break;
          case Qtrue:
            return Qtrue;
        }
    }
    return Qfalse;
}

из https://ruby -doc.org / core-2.2.0 / Array.html # method-i-include-3F вы увидите, что ruby ​​не использует ваш объектный оператор

РЕДАКТИРОВАТЬ: Как заявил Алексей-матюшкин (в комментариях), rb_equal_opt(e, item) сравнивает указатели и возвращает true

Инвертируя его, вы можете нажать на него:

class Foo
  def ==(other)
    puts "yay"
    true
  end
end

> f = Foo.new
=> #<Foo:0x0000000001048610> 
> [f].include?(f)
=> true 
> [f].include?(f.dup)
yay
=> true 

0 голосов
/ 25 января 2019

Я только что проверил исходный код из этого: https://apidock.com/ruby/Array/include%3F

Я считаю, что ruby ​​использовал оператор по умолчанию (rb_equal) вместо оператора объекта для этой функции.

...