From: nobuyoshi nakada Date: 2005-07-12T12:56:50+09:00 Subject: Re: accessing index inside map Hi, At Fri, 8 Jul 2005 23:02:11 +0900, Yukihiro Matsumoto wrote in [ruby-talk:147565]: > We have vague plan to make enumerating method to return Enumerator > when no block is given in the future, so that > > require 'enumerator' > (1..6).enum_for(:each_with_index).map{|x,i|[2,5].include?(i) ? x : x*2} > > would be > > (1..6).each_with_index.map{|x,i|[2,5].include?(i) ? x : x*2} > > then. It's much simpler isn't it? Is this plan going on? I noticed that #map and #collect return an Array if no block is given, instead of raising an exception. Index: enum.c =================================================================== RCS file: /cvs/ruby/src/ruby/enum.c,v retrieving revision 1.58 diff -U2 -p -r1.58 enum.c --- enum.c 30 Jun 2005 16:45:33 -0000 1.58 +++ enum.c 12 Jul 2005 03:54:56 -0000 @@ -18,4 +18,63 @@ VALUE rb_mEnumerable; static ID id_each, id_eqq, id_cmp; +#ifndef BUILTIN_ENUMERATOR +#define BUILTIN_ENUMERATOR 1 +#endif + +#if BUILTIN_ENUMERATOR +#define Init_enumerator static init_enumerator +#include "ext/enumerator/enumerator.c" +#undef Init_enumerator +#else +static ID id_enumerator; +#endif + +void +Init_enumerator() +{ +#if BUILTIN_ENUMERATOR + char *src = ruby_sourcefile = rb_source_filename("enumerator"); + init_enumerator(); + rb_provide(src); +#else + id_enumerator = rb_intern("Enumerator"); + rb_autoload(rb_mEnumerable, id_enumerator, "enumerator"); +#endif +} + +static VALUE +enumeratorize(argc, argv, obj) + int argc; + VALUE *argv; + VALUE obj; +{ + VALUE enum_method = ID2SYM(rb_frame_this_func()); +#if BUILTIN_ENUMERATOR + VALUE enum_obj = enumerator_allocate(rb_cEnumerator); + struct enumerator *ptr = enumerator_ptr(enum_obj); + + ptr->method = rb_obj_method(obj, enum_method); + if (rb_block_given_p()) { + ptr->proc = rb_block_proc(); + ptr->iter = enumerator_iter_i; + } + else { + ptr->iter = (VALUE (*) _((VALUE, struct enumerator *)))rb_yield; + } + if (argc) ptr->args = rb_ary_new4(argc, argv); + + return enum_obj; +#else + VALUE enumerator = rb_const_get(rb_mEnumerable, id_enumerator); + VALUE args = rb_ary_new2(argc + 2); + + RARRAY(args)->ptr[0] = obj; + RARRAY(args)->ptr[1] = enum_method; + MEMCPY(RARRAY(args)->ptr + 2, argv, VALUE, argc); + RARRAY(args)->len = argc + 2; + return rb_class_new_instance(RARRAY(args)->len, RARRAY(args)->ptr, enumerator); +#endif +} + VALUE rb_each(obj) @@ -115,4 +174,6 @@ enum_find(argc, argv, obj) rb_scan_args(argc, argv, "01", &if_none); + if (!rb_block_given_p()) + return enumeratorize(argc, argv, obj); rb_iterate(rb_each, obj, find_i, (VALUE)&memo); if (memo != Qundef) { @@ -152,6 +213,9 @@ enum_find_all(obj) VALUE obj; { - VALUE ary = rb_ary_new(); + VALUE ary; + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + + ary = rb_ary_new(); rb_iterate(rb_each, obj, find_all_i, ary); @@ -184,6 +248,9 @@ enum_reject(obj) VALUE obj; { - VALUE ary = rb_ary_new(); + VALUE ary; + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + + ary = rb_ary_new(); rb_iterate(rb_each, obj, reject_i, ary); @@ -226,7 +293,10 @@ enum_collect(obj) VALUE obj; { - VALUE ary = rb_ary_new(); + VALUE ary; + + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); - rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary); + ary = rb_ary_new(); + rb_iterate(rb_each, obj, collect_i, ary); return ary; @@ -344,4 +414,6 @@ enum_partition(obj) VALUE ary[2]; + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + ary[0] = rb_ary_new(); ary[1] = rb_ary_new(); @@ -477,4 +549,6 @@ enum_sort_by(obj) long i; + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + if (TYPE(obj) == T_ARRAY) { ary = rb_ary_new2(RARRAY(obj)->len); @@ -764,5 +838,6 @@ enum_min_by(obj) VALUE memo[2]; - rb_need_block(); + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + memo[0] = Qundef; memo[1] = Qnil; @@ -807,5 +882,6 @@ enum_max_by(obj) VALUE memo[2]; - rb_need_block(); + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + memo[0] = Qundef; memo[1] = Qnil; @@ -845,4 +921,6 @@ enum_member(obj, val) VALUE memo[2]; + if (!rb_block_given_p()) return enumeratorize(1, &val, obj); + memo[0] = val; memo[1] = Qfalse; @@ -882,5 +960,6 @@ enum_each_with_index(obj) VALUE memo = 0; - rb_need_block(); + if (!rb_block_given_p()) return enumeratorize(0, 0, obj); + rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo); return obj; Index: inits.c =================================================================== RCS file: /cvs/ruby/src/ruby/inits.c,v retrieving revision 1.9 diff -U2 -p -r1.9 inits.c --- inits.c 19 Dec 2003 03:58:57 -0000 1.9 +++ inits.c 12 Jul 2005 03:49:43 -0000 @@ -19,4 +19,5 @@ void Init_Comparable _((void)); void Init_Dir _((void)); void Init_Enumerable _((void)); +void Init_enumerator _((void)); void Init_Exception _((void)); void Init_syserr _((void)); @@ -81,4 +82,5 @@ rb_call_inits() Init_GC(); Init_marshal(); + Init_enumerator(); Init_version(); } -- Nobu Nakada