Почему `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