ruby-changes:15313
From: marcandre <ko1@a...>
Date: Sat, 3 Apr 2010 06:56:56 +0900 (JST)
Subject: [ruby-changes:15313] Ruby:r27200 (trunk): * array.c (rb_ary_product): Accept a block
marcandre 2010-04-03 06:56:34 +0900 (Sat, 03 Apr 2010) New Revision: 27200 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=27200 Log: * array.c (rb_ary_product): Accept a block [ruby-core:29045] Modified files: trunk/ChangeLog trunk/NEWS trunk/array.c Index: array.c =================================================================== --- array.c (revision 27199) +++ array.c (revision 27200) @@ -4052,12 +4052,16 @@ /* * call-seq: - * ary.product(other_ary, ...) + * ary.product(other_ary, ...) -> array + * ary.product(other_ary, ...) { |p| block } -> ary * - * Returns an array of all combinations of elements from all arrays. + * Returns an array of all combinations of elements from all arrays, * The length of the returned array is the product of the length - * of ary and the argument arrays + * of ary and the argument arrays. + * If given a block, <i>product</i> will yield all combinations + * and return self instead. * + * * [1,2,3].product([4,5]) # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] * [1,2].product([1,2]) # => [[1,1],[1,2],[2,1],[2,2]] * [1,2].product([3,4],[5,6]) # => [[1,3,5],[1,3,6],[1,4,5],[1,4,6], @@ -4074,7 +4078,7 @@ volatile VALUE t1 = tmpbuf(n, sizeof(int)); VALUE *arrays = (VALUE*)RSTRING_PTR(t0); /* The arrays we're computing the product of */ int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */ - VALUE result; /* The array we'll be returning */ + VALUE result = Qnil; /* The array we'll be returning, when no block given */ long i,j; long resultlen = 1; @@ -4091,7 +4095,7 @@ /* Compute the length of the result array; return [] if any is empty */ for (i = 0; i < n; i++) { long k = RARRAY_LEN(arrays[i]), l = resultlen; - if (k == 0) return rb_ary_new2(0); + if (k == 0) return rb_block_given_p() ? ary : rb_ary_new2(0); resultlen *= k; if (resultlen < k || resultlen < l || resultlen / k != l) { rb_raise(rb_eRangeError, "too big to product"); @@ -4099,7 +4103,9 @@ } /* Otherwise, allocate and fill in an array of results */ - result = rb_ary_new2(resultlen); + if (!rb_block_given_p()) { + result = rb_ary_new2(resultlen); + } for (i = 0; i < resultlen; i++) { int m; /* fill in one subarray */ @@ -4109,7 +4115,12 @@ } /* put it on the result array */ - rb_ary_push(result, subarray); + if(NIL_P(result)) { + rb_yield(subarray); + } + else { + rb_ary_push(result, subarray); + } /* * Increment the last counter. If it overflows, reset to 0 @@ -4126,7 +4137,7 @@ tmpbuf_discard(t0); tmpbuf_discard(t1); - return result; + return NIL_P(result) ? ary : result; } /* Index: ChangeLog =================================================================== --- ChangeLog (revision 27199) +++ ChangeLog (revision 27200) @@ -1,3 +1,7 @@ +Sat Apr 3 06:56:11 2010 Marc-Andre Lafortune <ruby-core@m...> + + * array.c (rb_ary_product): Accept a block [ruby-core:29045] + Sat Apr 3 04:46:00 2010 Tanaka Akira <akr@f...> * tool/file2lastrev.rb (VCS#relative_to): path and @srcdir may have Index: NEWS =================================================================== --- NEWS (revision 27199) +++ NEWS (revision 27200) @@ -22,7 +22,7 @@ * Array#sort_by! * extended methods: - * Array#{uniq,uniq!} can take a block. + * Array#{uniq,uniq!,product} can take a block. * Dir * new method: -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/