diff options
author | 卜部昌平 <shyouhei@ruby-lang.org> | 2019-12-04 15:31:51 +0900 |
---|---|---|
committer | 卜部昌平 <shyouhei@ruby-lang.org> | 2019-12-04 15:32:49 +0900 |
commit | 00bbdf4451d0e66f0f7823e77c47ac310614c1c3 (patch) | |
tree | 3be13b816dbaaa059709a79018cbc584d87e881f /range.c | |
parent | c6e3db0c66312af1e932c21006437419efa9ac75 (diff) |
implement Range#count
As matz requested in [Bug #16366].
Diffstat (limited to 'range.c')
-rw-r--r-- | range.c | 37 |
1 files changed, 37 insertions, 0 deletions
@@ -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); } |