From 181f815591030e9659643f8d6802eb5397ddac86 Mon Sep 17 00:00:00 2001 From: knu Date: Sun, 13 Apr 2008 14:59:55 +0000 Subject: [PATCH] * enum.c (enum_cycle): Make Enumerable#cycle do a finite loop when the number of cycles is specified. * array.c (rb_ary_cycle): Ditto for Array#cycle. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15991 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++++ array.c | 34 +++++++++++++++++++++++++--------- enum.c | 35 +++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2650b750f1..33c8697ad1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sun Apr 13 23:53:58 2008 Akinori MUSHA + + * enum.c (enum_cycle): Make Enumerable#cycle do a finite loop when + the number of cycles is specified. + + * array.c (rb_ary_cycle): Ditto for Array#cycle. + Sun Apr 13 18:52:27 2008 Nobuyoshi Nakada * thread_pthread.c (lock_func): should not check interrupts in diff --git a/array.c b/array.c index 577953a389..8ccbd97ff1 100644 --- a/array.c +++ b/array.c @@ -2938,24 +2938,40 @@ rb_ary_choice(VALUE ary) /* * call-seq: * ary.cycle {|obj| block } + * ary.cycle(n) {|obj| block } * - * Calls block repeatedly forever. + * Calls block for each element repeatedly _n_ times or + * forever if none or nil is given. If a non-positive number is + * given or the array is empty, does nothing. Returns nil if the + * loop has finished without getting interrupted. * * a = ["a", "b", "c"] * a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever. + * a.cycle(2) {|x| puts x } # print, a, b, c, a, b, c. * */ static VALUE -rb_ary_cycle(VALUE ary) +rb_ary_cycle(int argc, VALUE *argv, VALUE ary) { - long i; + long n, i; + VALUE nv = Qnil; - RETURN_ENUMERATOR(ary, 0, 0); - while (RARRAY_LEN(ary) > 0) { - for (i=0; i 0 && (n < 0 || 0 < n--)) { + for (i=0; iblock for each element of enum repeatedly - * forever. Returns nil if and only if the collection is empty. + * Calls block for each element of enum repeatedly _n_ + * times or forever if none or nil is given. If a non-positive + * number is given or the collection is empty, does nothing. Returns + * nil if the loop has finished without getting interrupted. + * * Enumerable#cycle saves elements in an internal array so changes * to enum after the first pass have no effect. * * a = ["a", "b", "c"] * a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever. + * a.cycle(2) {|x| puts x } # print, a, b, c, a, b, c. * */ static VALUE -enum_cycle(VALUE obj) +enum_cycle(int argc, VALUE *argv, VALUE obj) { VALUE ary; - long i, len; + VALUE nv = Qnil; + long n, i, len; - RETURN_ENUMERATOR(obj, 0, 0); + rb_scan_args(argc, argv, "01", &nv); + + RETURN_ENUMERATOR(obj, argc, argv); + if (NIL_P(nv)) { + n = -1; + } + else { + n = NUM2LONG(nv); + if (n <= 0) return Qnil; + } ary = rb_ary_new(); RBASIC(ary)->klass = 0; rb_block_call(obj, id_each, 0, 0, cycle_i, ary); len = RARRAY_LEN(ary); if (len == 0) return Qnil; - for (;;) { - for (i=0; i