为什么“Range#cover?”在比较失败时不引发异常?

Why doesn't `Range#cover?` raise an exception when comparison fails?

鉴于 Time 对象无法与 Fixnum 进行比较而无需显式转换:

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

以及 documentation for Range#cover? 所说的,

cover?(obj)true or false

Returns true if obj is between the begin and end of the range.

This tests begin <= obj <= end when exclude_end? is false and begin <= obj < end when exclude_end? is true.

我预计:

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

引发异常而不是默默地 return false。为什么它不引发异常?

可以理解的是,通过显式转换,比较有效:

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

我很确定这两个.include?和.cover?使用大小写质量运算符 (===),因此您获得的值与:

相同
p Time.now === 1000 #=> false

该文档未提及实现细节。 range_cover is implemented in terms of r_less (via r_cover_p). And 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% 的情况),你应该比较可比较的东西,对吧?在奇怪的情况下,您仍然会得到正确答案 ("this Time does not belong to this range of integers")。