1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

implement Range#count

As matz requested in [Bug #16366].
This commit is contained in:
卜部昌平 2019-12-04 15:31:51 +09:00
parent c6e3db0c66
commit 00bbdf4451
2 changed files with 41 additions and 0 deletions

37
range.c
View file

@ -1596,6 +1596,42 @@ range_alloc(VALUE klass)
return rb_struct_alloc_noinit(klass);
}
/*
* call-seq:
* range.count -> int
* range.count(item) -> int
* range.count { |obj| block } -> int
*
* Identical to Enumerable#count, except it returns Infinity for endless
* ranges.
*
*/
static VALUE
range_count(int argc, VALUE *argv, VALUE range)
{
if (argc != 0) {
/* It is odd for instace (1...).count(0) to return Infinity. Just let
* it loop. */
return rb_call_super(argc, argv);
}
else if (rb_block_given_p()) {
/* Likewise it is odd for instace (1...).count {|x| x == 0 } to return
* Infinity. Just let it loop. */
return rb_call_super(argc, argv);
}
else if (NIL_P(RANGE_END(range))) {
/* We are confident that the answer is Infinity. */
return DBL2NUM(HUGE_VAL);
}
else if (NIL_P(RANGE_BEG(range))) {
/* We are confident that the answer is Infinity. */
return DBL2NUM(HUGE_VAL);
}
else {
return rb_call_super(argc, argv);
}
}
/* A Range represents an interval---a set of values with a
* beginning and an end. Ranges may be constructed using the
* <em>s</em><code>..</code><em>e</em> and
@ -1733,4 +1769,5 @@ Init_Range(void)
rb_define_method(rb_cRange, "member?", range_include, 1);
rb_define_method(rb_cRange, "include?", range_include, 1);
rb_define_method(rb_cRange, "cover?", range_cover, 1);
rb_define_method(rb_cRange, "count", range_count, -1);
}

View file

@ -950,4 +950,8 @@ class TestRange < Test::Unit::TestCase
def test_beginless_range_iteration
assert_raise(TypeError) { (..1).each { } }
end
def test_count
assert_equal(Float::INFINITY, (1..).count)
end
end