Enumerable.cycle(n)

 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<RARRAY_LEN(ary); i++) {
  •  rb_yield(RARRAY_PTR(ary)[i]);
    
  • }
  • rb_scan_args(argc, argv, “01”, &nv);
  • RETURN_ENUMERATOR(ary, argc, argv);
  • if (NIL_P(nv)) {
  •    n = -1;
    
    }
  • else {
  •    n = NUM2LONG(nv);
    
  •    if (n <= 0) return Qnil;
    
  • }
  • while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n–)) {
  •    for (i=0; i<RARRAY_LEN(ary); i++) {
    
  •        rb_yield(RARRAY_PTR(ary)[i]);
    
  •    }
    
  • }
    return Qnil;
    }

@@ -3430,7 +3446,7 @@
rb_define_method(rb_cArray, “shuffle!”, rb_ary_shuffle_bang, 0);
rb_define_method(rb_cArray, “shuffle”, rb_ary_shuffle, 0);
rb_define_method(rb_cArray, “choice”, rb_ary_choice, 0);

  • rb_define_method(rb_cArray, “cycle”, rb_ary_cycle, 0);
  • rb_define_method(rb_cArray, “cycle”, rb_ary_cycle, -1);
    rb_define_method(rb_cArray, “permutation”, rb_ary_permutation, -1);
    rb_define_method(rb_cArray, “combination”, rb_ary_combination, 1);
    rb_define_method(rb_cArray, “product”, rb_ary_product, -1);
    Index: enum.c
    ===================================================================
    — enum.c (revision 15977)
    +++ enum.c (working copy)
    @@ -1656,33 +1656,48 @@
    /*
  • call-seq:
  • enum.cycle {|obj| block }
    
    • enum.cycle(n) {|obj| block }
      
    • Calls block 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 (;:wink: {
  • for (i=0; i<len; i++) {
  •  rb_yield(RARRAY_PTR(ary)[i]);
    
  • }
  • while (n < 0 || 0 < --n) {
  •    for (i=0; i<len; i++) {
    
  •        rb_yield(RARRAY_PTR(ary)[i]);
    
  •    }
    
    }
    return Qnil; /* not reached */
    }
    @@ -1741,7 +1756,7 @@
    rb_define_method(rb_mEnumerable, “take_while”, enum_take_while, 0);
    rb_define_method(rb_mEnumerable, “drop”, enum_drop, 1);
    rb_define_method(rb_mEnumerable, “drop_while”, enum_drop_while, 0);
  • rb_define_method(rb_mEnumerable, “cycle”, enum_cycle, 0);
  • rb_define_method(rb_mEnumerable, “cycle”, enum_cycle, -1);

    id_eqq = rb_intern("===");
    id_each = rb_intern(“each”);

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:34346] Enumerable.cycle(n)”
on Fri, 11 Apr 2008 23:55:44 +0900, “Akinori MUSHA”
[email protected] writes:

|e$B!!e(BEnumerable#cycle e$B$r2s?t;XDj2DG=$K$9$k$N$O$I$&$G$7$g$&$+!#e(B
|
|(1…3).cycle(2) { |obj| … } # 1,2,3,1,2,3

e$B%?%$%_%s%0E*$K$"$^$jNI$/$J$$$N$G$9$,!"JXMx$=$&$J$N$GF3F~$7$Fe(B
e$B$b$h$$$N$G$O$J$$$+$H;W$$$^$9!#e(B

|e$B!!2?2sL$J$N$+$rEO$9e(B #cycle_with_counter { |obj, counter| … } e$B$be(B
|e$B$[$7$$$+$b!#e(B(e$B2<$N%Q%C%A$K$O4^$^$l$F$$$^$;$se(B)

e$B$&!<$s!"$3$A$i$OJ]N1!#e(B