Почему `Range#cover?` Не вызывает исключение, если сравнение не удается?

При условии Time объекты нельзя сравнивать с Fixnum без явного приведения:

0 <= Time.now # => ArgumentError: comparison of Fixnum with Time failed
Time.now <= 10000000000 # => ArgumentError: comparison of Time with 10000000000 failed

и для чего нужна документацияRange#cover? говорит,

cover?(obj)true или же false

Возвращает true если obj находится между begin а также end из диапазона.

Это тесты begin <= obj <= end когда exclude_end? является false а также begin <= obj < end когда exclude_end? является true,

Я жду:

(0...10000000000).cover?(Time.now) # => false

возбудить исключение, а не молча вернуться false, Почему не возникает исключение?

Понятно, что при явном приведении сравнение работает:

(0...10000000000).cover?(Time.now.to_i) # => true

2 ответа

Решение

В документе не упоминаются детали реализации. range_cover реализуется с точки зрения r_less (с помощью r_cover_p). А также r_less Комментарий говорит:

/* compares _a_ and _b_ and returns:
 * < 0: a < b
 * = 0: a = b
 * > 0: a > b or non-comparable
 */

Вот источник r_cover_p:

static VALUE
r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val)
{
  if (r_less(beg, val) <= 0) {
    int excl = EXCL(range);
    if (r_less(val, end) <= -excl)
      return Qtrue;
  }
  return Qfalse;
}

Как мы видим, положительное число вернулось с любого из r_less вызовы приведут к Qfalse,

Я думаю, что причина, по которой док не упоминает об этом, заключается в том, чтобы держать это в курсе. Обычно (99,9999% случаев) вы должны сравнивать сопоставимые вещи, верно? И в нечетном случае вы этого не сделаете, вы все равно получите правильный ответ ("это время не относится к этому диапазону целых чисел").

Я почти уверен, что оба.include? и.cover? использует оператор качества дела (===) поэтому значение, которое вы получаете, равно

p Time.now === 1000 #=> false
Другие вопросы по тегам