From: nobuyoshi nakada Date: 2005-05-27T21:04:25+09:00 Subject: [ruby-dev:26245] Enumerable#{min_by,max_by} and etc. なかだです。 http://yowaken.dip.jp/tdiary/20050527.html#p02 のEnumerable#min_by, Enumerable#max_byが空のときにfalseを返すのとブロックがなくてもエラーに ならない、という動作を修正するパッチです。今のところデータを持ちまわる のにNODEを使っていますが、これはVALUEやVALUE[]を直接使っても充分じゃな いかという気がします。 また、内部で呼出すメソッドも見せなくてもいいのではないかと。 * enum.c (enum_min_by, enum_max_by): return nil if no iteration. * eval.c (rb_need_block): ensure a block is given. * eval.c (backtrace): skip successive frames sharing same node. Index: enum.c =================================================================== RCS file: /cvs/ruby/src/ruby/enum.c,v retrieving revision 1.54 diff -U2 -p -r1.54 enum.c --- enum.c 30 Oct 2004 06:56:17 -0000 1.54 +++ enum.c 27 May 2005 10:21:56 -0000 @@ -81,9 +81,8 @@ static VALUE find_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { if (RTEST(rb_yield(i))) { - memo->u2.value = Qtrue; - memo->u1.value = i; + *memo = i; rb_iter_break(); } @@ -112,11 +111,11 @@ enum_find(argc, argv, obj) VALUE obj; { - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, Qfalse, 0); + VALUE memo = Qundef; VALUE if_none; rb_scan_args(argc, argv, "01", &if_none); - rb_iterate(rb_each, obj, find_i, (VALUE)memo); - if (memo->u2.value) { - return memo->u1.value; + rb_iterate(rb_each, obj, find_i, (VALUE)&memo); + if (memo != Qundef) { + return memo; } if (!NIL_P(if_none)) { @@ -258,12 +257,11 @@ static VALUE inject_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { - if (memo->u2.value) { - memo->u2.value = Qfalse; - memo->u1.value = i; + if (*memo == Qundef) { + *memo = i; } else { - memo->u1.value = rb_yield_values(2, memo->u1.value, i); + *memo = rb_yield_values(2, *memo, i); } return Qnil; @@ -306,16 +304,9 @@ enum_inject(argc, argv, obj) VALUE *argv, obj; { - NODE *memo; - VALUE n; + VALUE memo = Qundef; - if (rb_scan_args(argc, argv, "01", &n) == 1) { - memo = rb_node_newnode(NODE_MEMO, n, Qfalse, 0); - } - else { - memo = rb_node_newnode(NODE_MEMO, Qnil, Qtrue, 0); - } - rb_iterate(rb_each, obj, inject_i, (VALUE)memo); - n = memo->u1.value; - return n; + rb_scan_args(argc, argv, "01", &memo); + rb_iterate(rb_each, obj, inject_i, (VALUE)&memo); + return memo; } @@ -508,8 +499,8 @@ static VALUE all_iter_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { if (!RTEST(rb_yield(i))) { - memo->u1.value = Qfalse; + *memo = Qfalse; rb_iter_break(); } @@ -520,8 +511,8 @@ static VALUE all_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { if (!RTEST(i)) { - memo->u1.value = Qfalse; + *memo = Qfalse; rb_iter_break(); } @@ -550,10 +541,7 @@ enum_all(obj) VALUE obj; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + VALUE result = Qtrue; - memo->u1.value = Qtrue; - rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)memo); - result = memo->u1.value; + rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result); return result; } @@ -562,8 +550,8 @@ static VALUE any_iter_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { if (RTEST(rb_yield(i))) { - memo->u1.value = Qtrue; + *memo = Qtrue; rb_iter_break(); } @@ -574,8 +562,8 @@ static VALUE any_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { if (RTEST(i)) { - memo->u1.value = Qtrue; + *memo = Qtrue; rb_iter_break(); } @@ -605,10 +593,7 @@ enum_any(obj) VALUE obj; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + VALUE result = Qfalse; - memo->u1.value = Qfalse; - rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)memo); - result = memo->u1.value; + rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result); return result; } @@ -617,15 +602,15 @@ static VALUE min_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { VALUE cmp; - if (NIL_P(memo->u1.value)) { - memo->u1.value = i; + if (NIL_P(*memo)) { + *memo = i; } else { - cmp = rb_funcall(i, id_cmp, 1, memo->u1.value); - if (rb_cmpint(cmp, i, memo->u1.value) < 0) { - memo->u1.value = i; + cmp = rb_funcall(i, id_cmp, 1, *memo); + if (rb_cmpint(cmp, i, *memo) < 0) { + *memo = i; } } @@ -636,15 +621,15 @@ static VALUE min_ii(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { VALUE cmp; - if (NIL_P(memo->u1.value)) { - memo->u1.value = i; + if (NIL_P(*memo)) { + *memo = i; } else { - cmp = rb_yield_values(2, i, memo->u1.value); - if (rb_cmpint(cmp, i, memo->u1.value) < 0) { - memo->u1.value = i; + cmp = rb_yield_values(2, i, *memo); + if (rb_cmpint(cmp, i, *memo) < 0) { + *memo = i; } } @@ -671,9 +656,7 @@ enum_min(obj) VALUE obj; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + VALUE result = Qnil; - rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)memo); - result = memo->u1.value; + rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)&result); return result; } @@ -682,15 +665,15 @@ static VALUE max_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { VALUE cmp; - if (NIL_P(memo->u1.value)) { - memo->u1.value = i; + if (NIL_P(*memo)) { + *memo = i; } else { - cmp = rb_funcall(i, id_cmp, 1, memo->u1.value); - if (rb_cmpint(cmp, i, memo->u1.value) > 0) { - memo->u1.value = i; + cmp = rb_funcall(i, id_cmp, 1, *memo); + if (rb_cmpint(cmp, i, *memo) > 0) { + *memo = i; } } @@ -701,15 +684,15 @@ static VALUE max_ii(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { VALUE cmp; - if (NIL_P(memo->u1.value)) { - memo->u1.value = i; + if (NIL_P(*memo)) { + *memo = i; } else { - cmp = rb_yield_values(2, i, memo->u1.value); - if (rb_cmpint(cmp, i, memo->u1.value) > 0) { - memo->u1.value = i; + cmp = rb_yield_values(2, i, *memo); + if (rb_cmpint(cmp, i, *memo) > 0) { + *memo = i; } } @@ -735,9 +718,7 @@ enum_max(obj) VALUE obj; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + VALUE result = Qnil; - rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)memo); - result = memo->u1.value; + rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)&result); return result; } @@ -746,16 +727,16 @@ static VALUE min_by_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { VALUE v; v = rb_yield(i); - if (NIL_P(memo->u1.value)) { - memo->u1.value = v; - memo->u2.value = i; - } - else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) { - memo->u1.value = v; - memo->u2.value = i; + if (NIL_P(memo[0])) { + memo[0] = v; + memo[1] = i; + } + else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) { + memo[0] = v; + memo[1] = i; } return Qnil; @@ -777,10 +758,10 @@ enum_min_by(obj) VALUE obj; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + VALUE memo[2]; + rb_need_block(); + memo[0] = memo[1] = Qnil; rb_iterate(rb_each, obj, min_by_i, (VALUE)memo); - result = memo->u2.value; - return result; + return memo[1]; } @@ -788,16 +769,16 @@ static VALUE max_by_i(i, memo) VALUE i; - NODE *memo; + VALUE *memo; { VALUE v; v = rb_yield(i); - if (NIL_P(memo->u1.value)) { - memo->u1.value = v; - memo->u2.value = i; - } - else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) { - memo->u1.value = v; - memo->u2.value = i; + if (NIL_P(memo[0])) { + memo[0] = v; + memo[1] = i; + } + else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) > 0) { + memo[0] = v; + memo[1] = i; } return Qnil; @@ -819,10 +800,10 @@ enum_max_by(obj) VALUE obj; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + VALUE memo[2]; + rb_need_block(); + memo[0] = memo[1] = Qnil; rb_iterate(rb_each, obj, max_by_i, (VALUE)memo); - result = memo->u2.value; - return result; + return memo[1]; } @@ -830,8 +811,8 @@ static VALUE member_i(item, memo) VALUE item; - NODE *memo; + VALUE *memo; { - if (rb_equal(item, memo->u1.value)) { - memo->u2.value = Qtrue; + if (rb_equal(item, memo[0])) { + memo[1] = Qtrue; rb_iter_break(); } @@ -856,10 +837,10 @@ enum_member(obj, val) VALUE obj, val; { - VALUE result; - NODE *memo = rb_node_newnode(NODE_MEMO, val, Qfalse, 0); + VALUE memo[2]; + memo[0] = val; + memo[1] = Qfalse; rb_iterate(rb_each, obj, member_i, (VALUE)memo); - result = memo->u2.value; - return result; + return memo[1]; } @@ -867,8 +848,8 @@ static VALUE each_with_index_i(val, memo) VALUE val; - NODE *memo; + VALUE *memo; { - rb_yield_values(2, val, INT2FIX(memo->u3.cnt)); - memo->u3.cnt++; + rb_yield_values(2, val, INT2FIX(*memo)); + ++*memo; return Qnil; } @@ -893,7 +874,8 @@ enum_each_with_index(obj) VALUE obj; { - NODE *memo = rb_node_newnode(NODE_MEMO, 0, 0, 0); + VALUE memo = 0; - rb_iterate(rb_each, obj, each_with_index_i, (VALUE)memo); + rb_need_block(); + rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo); return obj; } @@ -902,9 +884,9 @@ static VALUE zip_i(val, memo) VALUE val; - NODE *memo; + VALUE *memo; { - VALUE result = memo->u1.value; - VALUE args = memo->u2.value; - int idx = memo->u3.cnt++; + VALUE result = memo[0]; + VALUE args = memo[1]; + int idx = memo[2]++; VALUE tmp; int i; @@ -955,5 +937,5 @@ enum_zip(argc, argv, obj) int i; VALUE result; - NODE *memo; + VALUE memo[3]; for (i=0; inode)) { + for (; frame && (n = frame->node); frame = frame->prev) { if (frame->prev && frame->prev->this_func) { + if (frame->prev->node == n) continue; snprintf(buf, BUFSIZ, "%s:%d:in `%s'", n->nd_file, nd_line(n), @@ -6085,5 +6092,4 @@ backtrace(lev) } rb_ary_push(ary, rb_str_new2(buf)); - frame = frame->prev; } Index: ruby.h =================================================================== RCS file: /cvs/ruby/src/ruby/ruby.h,v retrieving revision 1.113 diff -U2 -p -r1.113 ruby.h --- ruby.h 15 May 2005 09:56:49 -0000 1.113 +++ ruby.h 27 May 2005 10:03:12 -0000 @@ -552,4 +552,5 @@ VALUE rb_yield_values __((int n, ...)); VALUE rb_yield_splat _((VALUE)); int rb_block_given_p _((void)); +void rb_need_block _((void)); VALUE rb_iterate _((VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE)); VALUE rb_rescue _((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE)); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦