summaryrefslogtreecommitdiff
path: root/range.c
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2019-12-04 15:31:51 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2019-12-04 15:32:49 +0900
commit00bbdf4451d0e66f0f7823e77c47ac310614c1c3 (patch)
tree3be13b816dbaaa059709a79018cbc584d87e881f /range.c
parentc6e3db0c66312af1e932c21006437419efa9ac75 (diff)
implement Range#count
As matz requested in [Bug #16366].
Diffstat (limited to 'range.c')
-rw-r--r--range.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/range.c b/range.c
index 07a0b40430..f701c16e6d 100644
--- a/range.c
+++ b/range.c
@@ -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);
}