* enum.c (enum_zip): honor length of the receiver, not the

shortest length.  [ruby-core:14738]

* enum.c (enum_zip): returns array not enumerator for no block
  form.  [ruby-core:14738]

* enumerator.c (next_ii): do not ignore multiple values yielded.

* array.c (rb_ary_zip): faster version without creating generators.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14952 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2008-01-08 09:50:01 +00:00
Родитель 1309c10332
Коммит 929faf7906
4 изменённых файлов: 128 добавлений и 16 удалений

Просмотреть файл

@ -2,6 +2,18 @@ Tue Jan 8 18:05:35 2008 Eric Hodel <drbrain@segment7.net>
* bin/ri, lib/rdoc/ri/*: Replace with Ryan Davis' cached ri.
Tue Jan 8 17:32:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
* enum.c (enum_zip): honor length of the receiver, not the
shortest length. [ruby-core:14738]
* enum.c (enum_zip): returns array not enumerator for no block
form. [ruby-core:14738]
* enumerator.c (next_ii): do not ignore multiple values yielded.
* array.c (rb_ary_zip): faster version without creating generators.
Tue Jan 8 15:47:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
* enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of

79
array.c
Просмотреть файл

@ -1983,6 +1983,84 @@ rb_ary_delete_if(VALUE ary)
return ary;
}
static VALUE
take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
{
if (args[1]-- == 0) rb_iter_break();
if (argc > 1) val = rb_ary_new4(argc, argv);
rb_ary_push(args[0], val);
return Qnil;
}
static VALUE
take_items(VALUE obj, long n)
{
VALUE result = rb_ary_new2(n);
VALUE args[2];
args[0] = result; args[1] = (VALUE)n;
rb_block_call(obj, rb_intern("each"), 0, 0, take_i, (VALUE)args);
return result;
}
/*
* call-seq:
* array.zip(arg, ...) -> an_array
* array.zip(arg, ...) {| arr | block } -> nil
*
* Converts any arguments to arrays, then merges elements of
* <i>self</i> with corresponding elements from each argument. This
* generates a sequence of <code>self.size</code> <em>n</em>-element
* arrays, where <em>n</em> is one more that the count of arguments. If
* the size of any argument is less than <code>enumObj.size</code>,
* <code>nil</code> values are supplied. If a block given, it is
* invoked for each output array, otherwise an array of arrays is
* returned.
*
* a = [ 4, 5, 6 ]
* b = [ 7, 8, 9 ]
*
* [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
* [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
* a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
*/
static VALUE
rb_ary_zip(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
int i, j;
long len;
VALUE result = Qnil;
len = RARRAY_LEN(ary);
for (i=0; i<argc; i++) {
argv[i] = take_items(argv[i], len);
}
if (!rb_block_given_p()) {
result = rb_ary_new2(len);
}
for (i=0; i<RARRAY_LEN(ary); i++) {
VALUE tmp = rb_ary_new2(argc+1);
rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
if (NIL_P(result)) {
rb_yield(tmp);
}
else {
rb_ary_push(result, tmp);
}
}
return result;
}
/*
* call-seq:
* array.transpose -> an_array
@ -3299,6 +3377,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);

49
enum.c
Просмотреть файл

@ -1346,6 +1346,18 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj)
}
static VALUE
call_next(VALUE *v)
{
return v[0] = rb_funcall(v[1], id_next, 0, 0);
}
static VALUE
call_stop(VALUE *v)
{
return v[0] = Qundef;
}
static VALUE
zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
{
@ -1357,8 +1369,20 @@ zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
for (i=0; i<RARRAY_LEN(args); i++) {
VALUE v = rb_funcall(RARRAY_PTR(args)[i], id_next, 0, 0);
rb_ary_push(tmp, v);
if (NIL_P(RARRAY_PTR(args)[i])) {
rb_ary_push(tmp, Qnil);
}
else {
VALUE v[2];
v[1] = RARRAY_PTR(args)[i];
rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, 0);
if (v[0] == Qundef) {
RARRAY_PTR(args)[i] = Qnil;
v[0] = Qnil;
}
rb_ary_push(tmp, v[0]);
}
}
if (NIL_P(result)) {
rb_yield(tmp);
@ -1369,12 +1393,6 @@ zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
return Qnil;
}
static VALUE
zip_b(NODE *memo)
{
return rb_block_call(memo->u3.value, id_each, 0, 0, zip_i, (VALUE)memo);
}
/*
* call-seq:
* enum.zip(arg, ...) => enumerator
@ -1401,16 +1419,19 @@ static VALUE
enum_zip(int argc, VALUE *argv, VALUE obj)
{
int i;
VALUE result;
ID conv;
NODE *memo;
VALUE result = Qnil;
conv = rb_intern("to_enum");
for (i=0; i<argc; i++) {
argv[i] = rb_funcall(argv[i], rb_intern("to_enum"), 1, ID2SYM(id_each));
argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
}
RETURN_ENUMERATOR(obj, argc, argv);
result = rb_block_given_p() ? Qnil : rb_ary_new();
memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), obj);
rb_rescue2(zip_b, (VALUE)memo, 0, 0, rb_eStopIteration, (VALUE)0);
if (!rb_block_given_p()) {
result = rb_ary_new();
}
memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0);
rb_block_call(obj, id_each, 0, 0, zip_i, (VALUE)memo);
return result;
}

Просмотреть файл

@ -365,9 +365,9 @@ enumerator_with_index(VALUE obj)
}
static VALUE
next_ii(VALUE i, VALUE obj)
next_ii(VALUE i, VALUE obj, int argc, VALUE *argv)
{
rb_fiber_yield(1, &i);
rb_fiber_yield(argc, argv);
return Qnil;
}