diff --git a/ChangeLog b/ChangeLog index 8bfc5d8836..480e670f8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,18 @@ Tue Jan 8 18:05:35 2008 Eric Hodel * bin/ri, lib/rdoc/ri/*: Replace with Ryan Davis' cached ri. +Tue Jan 8 17:32:07 2008 Yukihiro Matsumoto + + * 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 * enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of diff --git a/array.c b/array.c index c6ca7a8668..7c7fae0844 100644 --- a/array.c +++ b/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 + * self with corresponding elements from each argument. This + * generates a sequence of self.size n-element + * arrays, where n is one more that the count of arguments. If + * the size of any argument is less than enumObj.size, + * nil 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 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); diff --git a/enum.c b/enum.c index df3f103cab..faa688e11f 100644 --- a/enum.c +++ b/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; iu3.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