Given that Time
objects cannot be compared with Fixnum
without explicit casting:
0 <= Time.now # => ArgumentError: comparison of Fixnum with Time failed
Time.now <= 10000000000 # => ArgumentError: comparison of Time with 10000000000 failed
and what the documentation for Range#cover?
says,
cover?(obj)
→true
orfalse
Returns
true
ifobj
is between thebegin
andend
of the range.This tests
begin <= obj <= end
whenexclude_end?
isfalse
andbegin <= obj < end
whenexclude_end?
istrue
.
I expect:
(0...10000000000).cover?(Time.now) # => false
to raise an exception rather than silently return false
. Why doesn't it raise an exception?
It is understandable that, with explicit casting, the comparison works:
(0...10000000000).cover?(Time.now.to_i) # => true
The doc doesn't mention an implementation detail. range_cover
is implemented in terms of r_less
(via r_cover_p
). And r_less
comment says:
/* compares _a_ and _b_ and returns:
* < 0: a < b
* = 0: a = b
* > 0: a > b or non-comparable
*/
Here is the source of 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;
}
As we can see, a positive number returned from either of r_less
invocations will result in a Qfalse
.
Now, the reason why the doc doesn't mention it, I think, is to keep it light. Normally (99.9999% of cases), you're supposed to compare comparable things, right? And in the odd case you don't, you still get a correct answer ("this Time does not belong to this range of integers").