From: Akinori MUSHA Date: 2008-04-11T23:55:44+09:00 Subject: [ruby-dev:34346] Enumerable.cycle(n) --pgp-sign-Multipart_Fri_Apr_11_23:58:09_2008-1 Content-Type: text/plain; charset=ISO-2022-JP  Enumerable#cycle を回数指定可能にするのはどうでしょうか。 (1..3).cycle(2) { |obj| ... } # 1,2,3,1,2,3  何回目なのかを渡す #cycle_with_counter { |obj, counter| .. } も ほしいかも。(下のパッチには含まれていません) Index: array.c =================================================================== --- array.c (revision 15977) +++ array.c (working copy) @@ -2938,25 +2938,41 @@ /* * 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