In article <8764foo7s7.fsf / fsij.org>,
  Tanaka Akira <akr / fsij.org> writes:

>>> ここで疑問があるのですが、yield を 現在の 1.9 の b.call の動
>>> 作にしてしまわないのはなんででしょう?
>>
>> 返事を待っているんですが、なんでなんでしょう?
>
> やはり疑問で、とても知りたいのですが、なんでなんでしょう?

どこにこだわりがあるのかわからないので気に入るかどうかはわか
らないのですが、私としては次のようにしたらいいのではないかと
思っています。

* b.call の動作を基本とし、配列でデータを受け渡す
* |*x| でその配列を受け取れ、yield *x でその配列を設定できる
  (ラッパーが書ける)
* データを受け取るところで使い勝手と互換性を考えていくらか細
  工をする

どうでしょうか?

そして、この変更を行えば、pp.rb の変更を元に戻せますし、
test-all で失敗している drb などのいくつかの失敗が成功するよ
うになります。

Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.947
diff -u -p -r1.947 eval.c
--- eval.c	23 Sep 2006 21:29:47 -0000	1.947
+++ eval.c	26 Sep 2006 16:52:04 -0000
@@ -223,7 +223,7 @@ static int volatile freebsd_clear_carry_
 VALUE rb_cProc;
 VALUE rb_cBinding;
 static VALUE proc_alloc(VALUE,struct BLOCK*,int);
-static VALUE proc_invoke(VALUE,VALUE,VALUE,VALUE,int);
+static VALUE proc_invoke(VALUE,VALUE,VALUE,VALUE);
 static VALUE proc_lambda(void);
 static VALUE rb_f_binding(VALUE);
 static void rb_f_END(void);
@@ -1065,6 +1065,7 @@ typedef enum calling_scope {
 static VALUE rb_call(VALUE,VALUE,ID,int,const VALUE*,struct BLOCK*,calling_scope_t,int);
 static VALUE module_setup(VALUE,NODE*);
 
+static VALUE massign_args(VALUE,NODE*,VALUE,int);
 static VALUE massign(VALUE,NODE*,VALUE,int);
 static void assign(VALUE,NODE*,VALUE,int);
 static int formal_assign(VALUE, NODE*, int, const VALUE*, VALUE*);
@@ -2594,7 +2595,7 @@ call_trace_func(rb_event_t event, NODE *
 					    id?ID2SYM(id):Qnil,
 					    self ? rb_f_binding(self) : Qnil,
 					    klass?klass:Qnil),
-		    Qundef, 0, 0);
+		    Qundef, 0);
     }
     if (raised) thread_set_raised();
     POP_TAG();
@@ -2989,7 +2990,7 @@ rb_eval(VALUE self, NODE *n)
 	    ruby_current_node = node;
 	}
 	else {
-	    result = Qundef;	/* no arg */
+	    result = rb_ary_new2(0);	/* no arg */
 	}
 	SET_CURRENT_SOURCE();
 	result = rb_yield_0(result, 0, 0, 0);
@@ -4678,7 +4679,7 @@ rb_need_block(void)
 }
 
 static VALUE
-rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags)
+rb_yield_0(VALUE args, VALUE self, VALUE klass /* OK */, int flags)
 {
     NODE *node, *var;
     volatile VALUE result = Qnil;
@@ -4689,7 +4690,7 @@ rb_yield_0(VALUE val, VALUE self, VALUE 
     int old_vmode;
     struct FRAME frame;
     NODE *cnode = ruby_current_node;
-    int ary_args, lambda;
+    int lambda;
     int state, broken = 0;
 
     rb_need_block();
@@ -4723,37 +4724,26 @@ rb_yield_0(VALUE val, VALUE self, VALUE 
     node = block->body;
     var = block->var;
     lambda = block->flags & BLOCK_LAMBDA;
-    ary_args = flags & YIELD_ARY_ARGS;
     if (var) {
 	PUSH_TAG(PROT_NONE);
 	if ((state = EXEC_TAG()) == 0) {
 	    NODE *bvar = NULL;
 	  block_var:
 	    if (var == (NODE*)1) { /* no parameter || */
-		if (lambda && val != Qundef) {
-		    if (TYPE(val) != T_ARRAY) {
-			rb_raise(rb_eArgError, "wrong number of arguments (1 for 0)");
-		    }
-		    else if (RARRAY_LEN(val) != 0) {
+		if (lambda) {
+		    if (RARRAY_LEN(args) != 0) {
 			rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
-				 RARRAY_LEN(val));
+				 RARRAY_LEN(args));
 		    }
 		}
 	    }
-	    else if (var == (NODE*)2) {
-		if (TYPE(val) == T_ARRAY && RARRAY_LEN(val) != 0) {
-		    rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
-			     RARRAY_LEN(val));
-		}
-	    }
 	    else if (!bvar && nd_type(var) == NODE_BLOCK_PASS) {
 		bvar = var->nd_body;
 		var = var->nd_args;
 		goto block_var;
 	    }
 	    else if (nd_type(var) == NODE_ARGS) {
-		if (!ary_args) val = svalue_to_avalue(val);
-		formal_assign(self, var, RARRAY_LEN(val), RARRAY_PTR(val), 0);
+		formal_assign(self, var, RARRAY_LEN(args), RARRAY_PTR(args), 0);
 	    }
 	    else if (nd_type(var) == NODE_BLOCK) {
 		if (var->nd_next) {
@@ -4763,25 +4753,19 @@ rb_yield_0(VALUE val, VALUE self, VALUE 
 		goto block_var;
 	    }
 	    else if (nd_type(var) == NODE_MASGN) {
-		massign(self, var, val, lambda);
+		massign_args(self, var, args, lambda);
 	    }
 	    else {
 		if (lambda) {
-		    if (val == Qundef) {
-			rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
-		    }
-		    if (TYPE(val) == T_ARRAY && RARRAY_LEN(val) != 1) {
+		    if (RARRAY_LEN(args) != 1) {
 			rb_raise(rb_eArgError, "wrong number of arguments (%ld for 1)",
-				 RARRAY_LEN(val));
+				 RARRAY_LEN(args));
 		    }
 		}
-		if (ary_args) {
-		    if (RARRAY_LEN(val) == 0)
-			val = Qnil;
-		    else
-			val = RARRAY_PTR(val)[0];
-		}
-		assign(self, var, val, lambda);
+                if (RARRAY_LEN(args) == 0)
+                    assign(self, var, Qnil, lambda);
+                else
+                    assign(self, var, rb_ary_entry(args, 0), lambda);
 	    }
 	    if (bvar) {
 		struct BLOCK *b = ruby_frame->prev->prev->block;
@@ -4799,11 +4783,11 @@ rb_yield_0(VALUE val, VALUE self, VALUE 
 	POP_TAG();
 	if (state) goto pop_state;
     }
-    else if (lambda && ary_args && RARRAY_LEN(val) != 0 &&
-	     (!node || nd_type(node) != NODE_IFUNC ||
+    else if (lambda && RARRAY_LEN(args) != 0 &&
+	     (!node || (nd_type(node) != NODE_IFUNC && nd_type(node) != NODE_IFUNC1) ||
 	      node->nd_cfnc != bmcall)) {
 	rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
-		 RARRAY_LEN(val));
+		 RARRAY_LEN(args));
     }
     if (!node) {
 	state = 0;
@@ -4814,24 +4798,20 @@ rb_yield_0(VALUE val, VALUE self, VALUE 
     PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
     if ((state = EXEC_TAG()) == 0) {
       redo:
-	if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
-	    if (node->nd_state == YIELD_FUNC_AVALUE) {
-		val = svalue_to_avalue(val);
-	    }
-	    else {
-		if (val == Qundef && node->nd_state != YIELD_FUNC_SVALUE)
-		    val = Qnil;
-	    }
+	if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC || nd_type(node) == NODE_IFUNC1) {
 	    if ((block->flags&BLOCK_FROM_METHOD) && RTEST(block->block_obj)) {
 		struct BLOCK *data, _block;
 		Data_Get_Struct(block->block_obj, struct BLOCK, data);
 		_block = *data;
 		_block.uniq = block_unique++;
 		ruby_frame->block = &_block;
-		result = (*node->nd_cfnc)(val, node->nd_tval, self);
+		result = (*node->nd_cfnc)(args, node->nd_tval, self);
 	    }
+            else if (nd_type(node) == NODE_IFUNC1 && RARRAY_LEN(args) == 1) {
+                result = (*node->nd_cfnc)(rb_ary_entry(args, 0), node->nd_tval, self);
+            }
 	    else {
-		result = (*node->nd_cfnc)(val, node->nd_tval, self);
+		result = (*node->nd_cfnc)(args, node->nd_tval, self);
 	    }
 	}
 	else {
@@ -4911,7 +4891,10 @@ rb_yield_0(VALUE val, VALUE self, VALUE 
 VALUE
 rb_yield(VALUE val)
 {
-    return rb_yield_0(val, 0, 0, 0);
+    if (val == Qundef)
+        return rb_yield_0(rb_ary_new2(0), 0, 0, 0);
+    else
+        return rb_yield_0(rb_ary_new3(1, val), 0, 0, 0);
 }
 
 VALUE
@@ -4922,7 +4905,7 @@ rb_yield_values(int n, ...)
     VALUE val;
 
     if (n == 0) {
-	return rb_yield_0(Qundef, 0, 0, 0);
+	return rb_yield_0(rb_ary_new2(0), 0, 0, 0);
     }
     val = rb_ary_new2(n);
     va_start(args, n);
@@ -4933,6 +4916,16 @@ rb_yield_values(int n, ...)
     return rb_yield_0(val, 0, 0, 0);
 }
 
+VALUE
+rb_yield_splat(VALUE val)
+{
+    VALUE tmp = rb_check_array_type(val);
+    if (NIL_P(tmp)) {
+        rb_raise(rb_eArgError, "not an array");
+    }
+    return rb_yield_0(tmp, 0, 0, 0);
+}
+
 /*
  *  call-seq:
  *     loop {|| block }
@@ -4951,59 +4944,71 @@ static VALUE
 rb_f_loop(void)
 {
     for (;;) {
-	rb_yield_0(Qundef, 0, 0, 0);
+	rb_yield_0(rb_ary_new2(0), 0, 0, 0);
 	CHECK_INTS;
     }
     return Qnil;		/* dummy */
 }
 
 static VALUE
-massign(VALUE self, NODE *node, VALUE val, int pcall)
+massign_args(VALUE self, NODE *node, VALUE args, int lambda)
+{
+    if (lambda)
+        return massign(self, node, args, lambda);
+    if (!node->nd_head) /* |*v| */
+        return massign(self, node, args, lambda);
+    if (!node->nd_head->nd_next && !node->nd_args) /* |v| */
+        return massign(self, node, args, lambda);
+    /* |v1,|, |v1,*vs|, |v1,v2|, |v1,v2,|, |v1,v2,*vs|, etc. */
+    if (RARRAY_LEN(args) == 1)
+        return massign(self, node, rb_ary_entry(args, 0), lambda);
+    return massign(self, node, args, lambda);
+}
+
+static VALUE
+massign(VALUE self, NODE *node, VALUE val, int lambda)
 {
     NODE *list;
-    long i = 0, len;
+    long i = 0;
     volatile VALUE tmp;
-    VALUE *argv;
+    VALUE args;
 
     if (val == Qundef) {
-	argv = 0;
-	len = 0;
+        args = rb_ary_new2(0);
     }
     else {
 	tmp = rb_check_array_type(val);
 	if (NIL_P(tmp)) {
-	    argv = &val;
-	    len = (val == Qundef) ? 0 : 1;
+            args = rb_ary_new3(1, val);
 	}
 	else {
-	    argv = RARRAY_PTR(tmp);
-	    len = RARRAY_LEN(tmp);
+            args = tmp;
 	}
     }
     list = node->nd_head;
-    for (; list && i<len; i++) {
-	assign(self, list->nd_head, argv[i], pcall);
+    for (; list && i<RARRAY_LEN(args); i++) {
+	assign(self, list->nd_head, RARRAY_PTR(args)[i], lambda);
 	list = list->nd_next;
     }
-    if (pcall && list) goto arg_error;
-    if (node->nd_args) {
+    if (lambda && list) goto arg_error;
+    if (node->nd_args && (long)(node->nd_args) != -2) {
 	if ((long)(node->nd_args) == -1) {
 	    /* no check for mere `*' */
 	}
-	else if (!list && i<len) {
-	    assign(self, node->nd_args, rb_ary_new4(len-i, argv+i), pcall);
+	else if (!list && i<RARRAY_LEN(args)) {
+	    assign(self, node->nd_args, rb_ary_new4(RARRAY_LEN(args)-i, RARRAY_PTR(args)+i), lambda);
 	}
 	else {
-	    assign(self, node->nd_args, rb_ary_new2(0), pcall);
+	    assign(self, node->nd_args, rb_ary_new2(0), lambda);
 	}
     }
-    else if (pcall && i < len) {
+    else if (lambda && i < RARRAY_LEN(args)) {
 	goto arg_error;
     }
 
     while (list) {
 	i++;
-	assign(self, list->nd_head, Qnil, pcall);
+	assign(self, list->nd_head, Qnil, lambda);
 	list = list->nd_next;
     }
     return val;
@@ -5013,11 +5018,11 @@ massign(VALUE self, NODE *node, VALUE va
 	i++;
 	list = list->nd_next;
     }
-    rb_raise(rb_eArgError, "wrong number of arguments (%ld for %ld)", len, i);
+    rb_raise(rb_eArgError, "wrong number of arguments (%ld for %ld)", RARRAY_LEN(args), i);
 }
 
 static void
-assign(VALUE self, NODE *lhs, VALUE val, int pcall)
+assign(VALUE self, NODE *lhs, VALUE val, int lambda)
 {
     ruby_current_node = lhs;
     if (val == Qundef) {
@@ -5068,7 +5073,7 @@ assign(VALUE self, NODE *lhs, VALUE val,
 	break;
 
       case NODE_MASGN:
-	massign(self, lhs, val, pcall);
+	massign(self, lhs, val, lambda);
 	break;
 
       case NODE_CALL:
@@ -5115,7 +5120,7 @@ assign(VALUE self, NODE *lhs, VALUE val,
 	    }
 	    cnt = lhs->nd_head->nd_alen;
 	    if (RARRAY_LEN(val) < cnt) {
-		if (pcall) {
+		if (lambda) {
 		    rb_raise(rb_eArgError, "wrong number of arguments");
 		}
 		else {
@@ -5144,11 +5149,11 @@ assign(VALUE self, NODE *lhs, VALUE val,
 }
 
 VALUE
-rb_iterate(VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALUE data2)
+rb_iterate_0(enum node_type functype, VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALUE data2)
 {
     int state;
     volatile VALUE retval = Qnil;
-    NODE *node = NEW_IFUNC(bl_proc, data2);
+    NODE *node = NEW_NODE(functype, bl_proc, data2, 0);
     VALUE self = ruby_top_self;
 
     PUSH_TAG(PROT_LOOP);
@@ -5180,6 +5185,18 @@ rb_iterate(VALUE (*it_proc)(VALUE), VALU
     return retval;
 }
 
+VALUE
+rb_iterate_splat(VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALUE data2)
+{
+    return rb_iterate_0(NODE_IFUNC, it_proc, data1, bl_proc, data2);
+}
+
+VALUE
+rb_iterate(VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALUE data2)
+{
+    return rb_iterate_0(NODE_IFUNC1, it_proc, data1, bl_proc, data2);
+}
+
 struct iter_method_arg {
     VALUE obj;
     ID mid;
@@ -5198,6 +5215,18 @@ iterate_method(VALUE obj)
 }
 
 VALUE
+rb_block_call_splat(VALUE obj, ID mid, int argc, VALUE *argv, VALUE (*bl_proc)(ANYARGS), VALUE data2)
+{
+    struct iter_method_arg arg;
+
+    arg.obj = obj;
+    arg.mid = mid;
+    arg.argc = argc;
+    arg.argv = argv;
+    return rb_iterate_splat(iterate_method, (VALUE)&arg, bl_proc, data2);
+}
+
+VALUE
 rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv, VALUE (*bl_proc)(ANYARGS), VALUE data2)
 {
     struct iter_method_arg arg;
@@ -5776,7 +5805,7 @@ rb_call0(VALUE klass, VALUE recv, ID id,
 	    Data_Get_Struct(body->nd_cval, struct BLOCK, data);
 	    EXEC_EVENT_HOOK(RUBY_EVENT_CALL, data->body, recv, id, klass);
 	}
-	result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass, 1);
+	result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
 	if (event_hooks) {
 	    EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
 	}
@@ -6484,10 +6513,8 @@ static VALUE
 yield_under_i(VALUE arg)
 {
     VALUE *args = (VALUE *)arg;
-    int flags = YIELD_PUBLIC_DEF;
-    if (args[0] != Qundef) flags |= YIELD_ARY_ARGS;
 
-    return rb_yield_0(args[0], args[1], ruby_cbase, flags);
+    return rb_yield_0(args[0], args[1], ruby_cbase, YIELD_PUBLIC_DEF);
 }
 
 /* block eval under the class/module context */
@@ -6507,7 +6534,7 @@ specific_eval(int argc, VALUE *argv, VAL
 	if (argc > 0) {
 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
 	}
-	return yield_under(klass, self, Qundef);
+	return yield_under(klass, self, rb_ary_new2(0));
     }
     else {
 	const char *file = "(eval)";
@@ -7666,7 +7693,7 @@ call_end_proc(VALUE data)
     PUSH_FRAME(Qfalse);
     ruby_frame->self = ruby_frame->prev->self;
     ruby_frame->node = 0;
-    proc_invoke(data, rb_ary_new2(0), Qundef, 0, 1);
+    proc_invoke(data, rb_ary_new2(0), Qundef, 0);
     POP_FRAME();
 }
 
@@ -8426,7 +8453,7 @@ block_orphan(struct BLOCK *data)
 }
 
 static VALUE
-proc_invoke(VALUE proc, VALUE args /* OK */, VALUE self, VALUE klass, int call)
+proc_invoke(VALUE proc, VALUE args /* OK */, VALUE self, VALUE klass)
 {
     struct BLOCK _block;
     struct BLOCK *data;
@@ -8434,12 +8461,10 @@ proc_invoke(VALUE proc, VALUE args /* OK
     int state;
     volatile int safe = ruby_safe_level;
     volatile VALUE old_wrapper = ruby_wrapper;
-    volatile int pcall, lambda;
+    volatile int lambda;
     VALUE bvar = 0;
 
     Data_Get_Struct(proc, struct BLOCK, data);
-    pcall = call ? YIELD_ARY_ARGS : 0;
-    pcall |= YIELD_PROC_INVOKE;
     lambda = data->flags & BLOCK_LAMBDA;
     if (rb_block_given_p() && ruby_frame->callee) {
 	if (klass != ruby_frame->this_class)
@@ -8454,7 +8479,7 @@ proc_invoke(VALUE proc, VALUE args /* OK
     _block.block_obj = bvar;
     if (self != Qundef) _block.frame.self = self;
     if (klass) _block.frame.this_class = klass;
-    _block.frame.argc = call ? RARRAY_LEN(args) : 1;
+    _block.frame.argc = RARRAY_LEN(args);
     _block.frame.flags = ruby_frame->flags;
     if (_block.frame.argc && (ruby_frame->flags & FRAME_DMETH)) {
         NEWOBJ(scope, struct SCOPE);
@@ -8469,7 +8494,7 @@ proc_invoke(VALUE proc, VALUE args /* OK
     state = EXEC_TAG();
     if (state == 0) {
 	proc_set_safe_level(proc);
-	result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0, pcall);
+	result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0, YIELD_PROC_INVOKE);
     }
     else if (TAG_DST()) {
 	result = prot_tag->retval;
@@ -8493,8 +8518,7 @@ proc_invoke(VALUE proc, VALUE args /* OK
 	JUMP_TAG(state);
       case TAG_RETURN:
 	if (result != Qundef) {
-	    if (pcall) break;
-	    return_jump(result);
+	    break;
 	}
       default:
 	JUMP_TAG(state);
@@ -8502,74 +8526,37 @@ proc_invoke(VALUE proc, VALUE args /* OK
     return result;
 }
 
-/* CHECKME: are the argument checking semantics correct? */
-
 /*
  *  call-seq:
  *     prc.call(params,...)   => obj
+ *     prc.yield(params,...)   => obj
  *     prc[params,...]        => obj
  *  
  *  Invokes the block, setting the block's parameters to the values in
  *  <i>params</i> using something close to method calling semantics.
- *  Generates a warning if multiple values are passed to a proc that
- *  expects just one (previously this silently converted the parameters
- *  to an array).
  *
- *  For procs created using <code>Kernel.proc</code>, generates an
- *  error if the wrong number of parameters
- *  are passed to a proc with multiple parameters. For procs created using
- *  <code>Proc.new</code>, extra parameters are silently discarded.
+ *  For procs created using <code>Kernel.lambda</code>, generates an
+ *  error if the wrong number of parameters are passed to a proc with
+ *  multiple parameters.
+ *  For procs created using <code>Proc.new</code> or
+ *  <code>Kernel.proc</code>, extra parameters are silently discarded.
  *
- *  Returns the value of the last expression evaluated in the block. See
- *  also <code>Proc#yield</code>.
+ *  Returns the value of the last expression evaluated in the block.
  *     
  *     a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
  *     a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
+ *     a_proc.yield(9, 1, 2, 3)  #=> [9, 18, 27]
  *     a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
  *     a_proc = Proc.new {|a,b| a}
- *     a_proc.call(1,2,3)
- *     
- *  <em>produces:</em>
- *     
- *     prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError)
- *     	from prog.rb:4:in `call'
- *     	from prog.rb:5
+ *     a_proc.call(1,2,3)        #=> 1
+ *     a_lambda = lambda {|a| p a }
+ *     a_lambda.call(1,2)        #=> wrong number of arguments (2 for 1) (ArgumentError)
  */
 
 VALUE
 rb_proc_call(VALUE proc, VALUE args /* OK */)
 {
-    return proc_invoke(proc, args, Qundef, 0, 1);
-}
-
-/*
- *  call-seq:
- *     prc.yield(params,...)   => obj
- *  
- *  Invokes the block, setting the block's parameters to the values in
- *  <i>params</i> in the same manner the yield statement does.
- *     
- *     a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
- *     a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]
- *     a_proc.yield([9, 1, 2, 3]) #=> [9, 18, 27]
- *     a_proc = Proc.new {|a,b| a}
- *     a_proc.yield(1,2,3)	  # => [1]
- */
-
-VALUE
-rb_proc_yield(int argc, VALUE *argv, VALUE proc)
-{
-    switch (argc) {
-      case 1:
-	if (!NIL_P(argv[0])) {
-	    return proc_invoke(proc, argv[0], Qundef, 0, 0);
-	}
-	/* fall through */
-      case 0:
-	return proc_invoke(proc, Qundef, Qundef, 0, 0);
-      default:
-	return proc_invoke(proc, rb_ary_new4(argc, argv), Qundef, 0, 0);
-    }
+    return proc_invoke(proc, args, Qundef, 0);
 }
 
 /* :nodoc: */
@@ -8591,7 +8578,7 @@ rb_proc_arity(VALUE proc)
     var = data->var;
     if (var == 0) {
 	if (!data->body) return 0;
-	if (nd_type(data->body) == NODE_IFUNC &&
+	if ((nd_type(data->body) == NODE_IFUNC || nd_type(data->body) == NODE_IFUNC1) &&
 	    data->body->nd_cfnc == bmcall) {
 	    return method_arity(data->body->nd_tval);
 	}
@@ -8614,7 +8601,7 @@ rb_proc_arity(VALUE proc)
 	    n++;
 	    list = list->nd_next;
 	}
-	if (var->nd_args) {
+	if (var->nd_args && var->nd_args != (NODE *)-2) {
 	    if (var->nd_args != (NODE *)-1 && nd_type(var->nd_args) == NODE_POSTARG) {
 		return -n-1-var->nd_args->nd_head->nd_alen;
 	    }
@@ -9399,7 +9386,7 @@ rb_proc_new(
     VALUE val)
 {
     struct BLOCK *data;
-    VALUE proc = rb_iterate((VALUE(*)(VALUE))mproc, 0, func, val);
+    VALUE proc = rb_iterate_splat((VALUE(*)(VALUE))mproc, 0, func, val);
 
     Data_Get_Struct(proc, struct BLOCK, data);
     data->body->nd_state = YIELD_FUNC_AVALUE;
@@ -9424,7 +9411,7 @@ method_proc(VALUE method)
     if (nd_type(mdata->body) == NODE_BMETHOD) {
 	return mdata->body->nd_cval;
     }
-    proc = rb_iterate((VALUE(*)(VALUE))mproc, 0, bmcall, method);
+    proc = rb_iterate_splat((VALUE(*)(VALUE))mproc, 0, bmcall, method);
     Data_Get_Struct(proc, struct BLOCK, bdata);
     bdata->body->nd_file = mdata->body->nd_file;
     nd_set_line(bdata->body, nd_line(mdata->body));
@@ -9586,7 +9573,7 @@ Init_Proc(void)
     rb_define_method(rb_cProc, "clone", proc_clone, 0);
     rb_define_method(rb_cProc, "dup", proc_dup, 0);
     rb_define_method(rb_cProc, "call", rb_proc_call, -2);
-    rb_define_method(rb_cProc, "yield", rb_proc_yield, -1);
+    rb_define_method(rb_cProc, "yield", rb_proc_call, -2);
     rb_define_method(rb_cProc, "arity", proc_arity, 0);
     rb_define_method(rb_cProc, "[]", rb_proc_call, -2);
     rb_define_method(rb_cProc, "==", proc_eq, 1);
@@ -11975,7 +11962,7 @@ rb_thread_start_1(void)
     if ((state = EXEC_TAG()) == 0) {
 	if (THREAD_SAVE_CONTEXT(th) == 0) {
 	    new_thread.thread = 0;
-	    th->result = rb_proc_yield(RARRAY_LEN(arg), RARRAY_PTR(arg), proc);
+	    th->result = rb_proc_call(proc, arg);
 	}
 	th = th_save;
     }
@@ -13071,7 +13058,7 @@ rb_f_catch(VALUE dmy, VALUE tag)
     tag = ID2SYM(rb_to_id(tag));
     PUSH_TAG(tag);
     if ((state = EXEC_TAG()) == 0) {
-	val = rb_yield_0(tag, 0, 0, 0);
+	val = rb_yield_0(rb_ary_new3(1, tag), 0, 0, 0);
     }
     else if (state == TAG_THROW && tag == prot_tag->dst) {
 	val = prot_tag->retval;
Index: hash.c
===================================================================
RCS file: /src/ruby/hash.c,v
retrieving revision 1.172
diff -u -p -r1.172 hash.c
--- hash.c	25 Sep 2006 05:57:37 -0000	1.172
+++ hash.c	26 Sep 2006 16:52:04 -0000
@@ -994,7 +994,7 @@ static int
 each_pair_i(VALUE key, VALUE value)
 {
     if (key == Qundef) return ST_CONTINUE;
-    rb_yield(rb_assoc_new(key, value));
+    rb_yield_values(2, key, value);
     return ST_CONTINUE;
 }
 
@@ -1027,7 +1027,7 @@ static int
 each_i(VALUE key, VALUE value)
 {
     if (key == Qundef) return ST_CONTINUE;
-    rb_yield_values(2, key, value);
+    rb_yield(rb_assoc_new(key, value));
     return ST_CONTINUE;
 }
 
Index: node.h
===================================================================
RCS file: /src/ruby/node.h,v
retrieving revision 1.78
diff -u -p -r1.78 node.h
--- node.h	23 Sep 2006 21:29:47 -0000	1.78
+++ node.h	26 Sep 2006 16:52:04 -0000
@@ -120,6 +120,7 @@ enum node_type {
     NODE_BMETHOD,
     NODE_MEMO,
     NODE_IFUNC,
+    NODE_IFUNC1,
     NODE_DSYM,
     NODE_ATTRASGN,
     NODE_PRELUDE,
@@ -248,6 +249,7 @@ extern NODE *ruby_top_cref;
 #define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_RFUNC(a,d))
 #define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
 #define NEW_IFUNC(f,c) NEW_NODE(NODE_IFUNC,f,c,0)
+#define NEW_IFUNC1(f,c) NEW_NODE(NODE_IFUNC1,f,c,0)
 #define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
 #define NEW_SCOPE(b) NEW_NODE(NODE_SCOPE,local_tbl(),0,(b))
 #define NEW_BLOCK(a) NEW_NODE(NODE_BLOCK,a,0,0)
Index: parse.y
===================================================================
RCS file: /src/ruby/parse.y,v
retrieving revision 1.460
diff -u -p -r1.460 parse.y
--- parse.y	25 Sep 2006 05:57:37 -0000	1.460
+++ parse.y	26 Sep 2006 16:52:04 -0000
@@ -1228,7 +1228,7 @@ mlhs		: mlhs_basic
 		| tLPAREN mlhs_entry rparen
 		    {
 		    /*%%%*/
-			$$ = $2;
+			$$ = NEW_MASGN(NEW_LIST($2), 0);
 		    /*%
 			$$ = dispatch1(mlhs_paren, $2);
 		    %*/
@@ -2888,13 +2888,7 @@ block_param0	: mlhs_item
 block_param	: block_param0
 		    {
 		    /*%%%*/
-                        if ($1->nd_alen == 1) {
-                            $$ = $1->nd_head;
-                            rb_gc_force_recycle((VALUE)$1);
-                        }
-                        else {
-                            $$ = NEW_MASGN($1, 0);
-                        }
+                        $$ = NEW_MASGN($1, 0);
 		    /*%
 			$$ = blockvar_new($1);
 		    %*/
@@ -2902,7 +2896,7 @@ block_param	: block_param0
 		| block_param0 ','
 		    {
 		    /*%%%*/
-			$$ = NEW_MASGN($1, 0);
+			$$ = NEW_MASGN($1, -2);
 		    /*%
 			$$ = blockvar_new($1);
 		    %*/
@@ -7837,11 +7831,7 @@ new_yield(NODE *node)
 
     if (node) {
 	no_blockarg(node);
-	if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) {
-	    node = node->nd_head;
-	    state = Qfalse;
-	}
-	else if (node && nd_type(node) == NODE_SPLAT) {
+	if (node && nd_type(node) == NODE_SPLAT) {
 	    state = Qtrue;
 	}
     }
Index: ruby.h
===================================================================
RCS file: /src/ruby/ruby.h,v
retrieving revision 1.153
diff -u -p -r1.153 ruby.h
--- ruby.h	23 Sep 2006 21:29:47 -0000	1.153
+++ ruby.h	26 Sep 2006 16:52:04 -0000
@@ -646,7 +646,9 @@ 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_iterate_splat(VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE);
 VALUE rb_block_call(VALUE,ID,int,VALUE*,VALUE(*)(ANYARGS),VALUE);
+VALUE rb_block_call_splat(VALUE,ID,int,VALUE*,VALUE(*)(ANYARGS),VALUE);
 VALUE rb_rescue(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE);
 VALUE rb_rescue2(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE,...);
 VALUE rb_ensure(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE);
Index: string.c
===================================================================
RCS file: /src/ruby/string.c,v
retrieving revision 1.280
diff -u -p -r1.280 string.c
--- string.c	22 Sep 2006 09:08:58 -0000	1.280
+++ string.c	26 Sep 2006 16:52:04 -0000
@@ -4087,7 +4087,10 @@ rb_str_scan(VALUE str, VALUE pat)
     while (!NIL_P(result = scan_once(str, pat, &start))) {
 	match = rb_backref_get();
 	rb_match_busy(match);
-	rb_yield(result);
+        if (TYPE(result) == T_STRING)
+            rb_yield(result);
+        else
+            rb_yield_splat(result);
 	str_mod_check(str, p, len);
 	rb_backref_set(match);	/* restore $~ value */
     }
Index: lib/getoptlong.rb
===================================================================
RCS file: /src/ruby/lib/getoptlong.rb,v
retrieving revision 1.16
diff -u -p -r1.16 getoptlong.rb
--- lib/getoptlong.rb	10 Jun 2006 01:20:23 -0000	1.16
+++ lib/getoptlong.rb	26 Sep 2006 16:52:04 -0000
@@ -289,7 +289,7 @@ class GetoptLong
     @canonical_names.clear
     @argument_flags.clear
 
-    arguments.each do |*arg|
+    arguments.each do |arg|
       #
       # Find an argument flag and it set to `argument_flag'.
       #
Index: lib/mkmf.rb
===================================================================
RCS file: /src/ruby/lib/mkmf.rb,v
retrieving revision 1.263
diff -u -p -r1.263 mkmf.rb
--- lib/mkmf.rb	26 Sep 2006 16:05:21 -0000	1.263
+++ lib/mkmf.rb	26 Sep 2006 16:52:04 -0000
@@ -1230,7 +1230,7 @@ EXTSTATIC = #{$static || ""}
 STATIC_LIB = #{staticlib unless $static.nil?}
 #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
 "
-  install_dirs.each {|*d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
+  install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
   n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET).'
   mfile.print "
 TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
Index: lib/optparse.rb
===================================================================
RCS file: /src/ruby/lib/optparse.rb,v
retrieving revision 1.69
diff -u -p -r1.69 optparse.rb
--- lib/optparse.rb	26 Sep 2006 15:49:40 -0000	1.69
+++ lib/optparse.rb	26 Sep 2006 16:52:04 -0000
@@ -1422,7 +1422,7 @@ class OptionParser
   def search(id, key)
     block_given = block_given?
     visit(:search, id, key) do |k|
-      return block_given ? yield(k) : k
+      return block_given ? yield(*k) : k
     end
   end
   private :search
Index: lib/pp.rb
===================================================================
RCS file: /src/ruby/lib/pp.rb,v
retrieving revision 1.50
diff -u -p -r1.50 pp.rb
--- lib/pp.rb	11 Jul 2006 04:58:43 -0000	1.50
+++ lib/pp.rb	26 Sep 2006 16:52:04 -0000
@@ -220,13 +220,13 @@ class PP < PrettyPrint
     def seplist(list, sep=nil, iter_method=:each) # :yield: element
       sep ||= lambda { comma_breakable }
       first = true
-      list.__send__(iter_method) {|v|
+      list.__send__(iter_method) {|*v|
         if first
           first = false
         else
           sep.call
         end
-        yield(v)
+        yield(*v)
       }
     end
 
Index: sample/test.rb
===================================================================
RCS file: /src/ruby/sample/test.rb,v
retrieving revision 1.102
diff -u -p -r1.102 test.rb
--- sample/test.rb	25 Sep 2006 06:07:35 -0000	1.102
+++ sample/test.rb	26 Sep 2006 16:52:04 -0000
@@ -134,13 +134,13 @@ def f; yield [[]]; end; f {|a| test_ok(a
 def f; yield [*[]]; end; f {|a| test_ok(a == [])}
 def f; yield [*[1]]; end; f {|a| test_ok(a == [1])}
 def f; yield [*[1,2]]; end; f {|a| test_ok(a == [1,2])}
-def f; yield *[]; end; f {|a| test_ok(a == [])}
-def f; yield *[1]; end; f {|a| test_ok(a == [1])}
-def f; yield *[nil]; end; f {|a| test_ok(a == [nil])}
-def f; yield *[[]]; end; f {|a| test_ok(a == [[]])}
-def f; yield *[*[]]; end; f {|a| test_ok(a == [])}
-def f; yield *[*[1]]; end; f {|a| test_ok(a == [1])}
-def f; yield *[*[1,2]]; end; f {|a| test_ok(a == [1,2])}
+def f; yield *[]; end; f {|a| test_ok(a == nil)}
+def f; yield *[1]; end; f {|a| test_ok(a == 1)}
+def f; yield *[nil]; end; f {|a| test_ok(a == nil)}
+def f; yield *[[]]; end; f {|a| test_ok(a == [])}
+def f; yield *[*[]]; end; f {|a| test_ok(a == nil)}
+def f; yield *[*[1]]; end; f {|a| test_ok(a == 1)}
+def f; yield *[*[1,2]]; end; f {|a| test_ok(a == 1)}
 
 def f; yield; end; f {|a,| test_ok(a == nil)}
 def f; yield nil; end; f {|a,| test_ok(a == nil)}
@@ -156,7 +156,7 @@ def f; yield [*[1,2]]; end; f {|a,| test
 def f; yield *[]; end; f {|a,| test_ok(a == nil)}
 def f; yield *[1]; end; f {|a,| test_ok(a == 1)}
 def f; yield *[nil]; end; f {|a,| test_ok(a == nil)}
-def f; yield *[[]]; end; f {|a,| test_ok(a == [])}
+def f; yield *[[]]; end; f {|a,| test_ok(a == nil)}
 def f; yield *[*[]]; end; f {|a,| test_ok(a == nil)}
 def f; yield *[*[1]]; end; f {|a,| test_ok(a == 1)}
 def f; yield *[*[1,2]]; end; f {|a,| test_ok(a == 1)}
@@ -164,14 +164,14 @@ def f; yield *[*[1,2]]; end; f {|a,| tes
 def f; yield; end; f {|*a| test_ok(a == [])}
 def f; yield nil; end; f {|*a| test_ok(a == [nil])}
 def f; yield 1; end; f {|*a| test_ok(a == [1])}
-def f; yield []; end; f {|*a| test_ok(a == [])}
-def f; yield [1]; end; f {|*a| test_ok(a == [1])}
-def f; yield [nil]; end; f {|*a| test_ok(a == [nil])}
-def f; yield [[]]; end; f {|*a| test_ok(a == [[]])}
-def f; yield [1,2]; end; f {|*a| test_ok(a == [1,2])}
-def f; yield [*[]]; end; f {|*a| test_ok(a == [])}
-def f; yield [*[1]]; end; f {|*a| test_ok(a == [1])}
-def f; yield [*[1,2]]; end; f {|*a| test_ok(a == [1,2])}
+def f; yield []; end; f {|*a| test_ok(a == [[]])}
+def f; yield [1]; end; f {|*a| test_ok(a == [[1]])}
+def f; yield [nil]; end; f {|*a| test_ok(a == [[nil]])}
+def f; yield [[]]; end; f {|*a| test_ok(a == [[[]]])}
+def f; yield [1,2]; end; f {|*a| test_ok(a == [[1,2]])}
+def f; yield [*[]]; end; f {|*a| test_ok(a == [[]])}
+def f; yield [*[1]]; end; f {|*a| test_ok(a == [[1]])}
+def f; yield [*[1,2]]; end; f {|*a| test_ok(a == [[1,2]])}
 
 def f; yield *[]; end; f {|*a| test_ok(a == [])}
 def f; yield *[1]; end; f {|*a| test_ok(a == [1])}
@@ -195,7 +195,7 @@ def f; yield [*[1,2]]; end; f {|a,b,*c| 
 def f; yield *[]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])}
 def f; yield *[1]; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])}
 def f; yield *[nil]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])}
-def f; yield *[[]]; end; f {|a,b,*c| test_ok([a,b,c] == [[],nil,[]])}
+def f; yield *[[]]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])}
 def f; yield *[*[]]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])}
 def f; yield *[*[1]]; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])}
 def f; yield *[*[1,2]]; end; f {|a,b,*c| test_ok([a,b,c] == [1,2,[]])}
@@ -964,23 +964,23 @@ IterTest.new([1]).each1 {|x| test_ok(x =
 IterTest.new([2]).each2 {|x| test_ok(x == [2])}
 #IterTest.new([3]).each3 {|x| test_ok(x == 3)}
 IterTest.new([4]).each4 {|x| test_ok(x == 4)}
-IterTest.new([5]).each5 {|x| test_ok(x == [5])}
+IterTest.new([5]).each5 {|x| test_ok(x == 5)}
 IterTest.new([6]).each6 {|x| test_ok(x == [6])}
 #IterTest.new([7]).each7 {|x| test_ok(x == 7)}
 IterTest.new([8]).each8 {|x| test_ok(x == 8)}
 
 IterTest.new([[0]]).each0 {|x| test_ok(x == [0])}
-IterTest.new([[1]]).each1 {|x| test_ok(x == 1)}
-IterTest.new([[2]]).each2 {|x| test_ok(x == [2])}
+IterTest.new([[1]]).each1 {|x| test_ok(x == [1])}
+IterTest.new([[2]]).each2 {|x| test_ok(x == [[2]])}
 IterTest.new([[3]]).each3 {|x| test_ok(x == 3)}
 IterTest.new([[4]]).each4 {|x| test_ok(x == [4])}
 IterTest.new([[5]]).each5 {|x| test_ok(x == [5])}
-IterTest.new([[6]]).each6 {|x| test_ok(x == [6])}
-IterTest.new([[7]]).each7 {|x| test_ok(x == [7])}
+IterTest.new([[6]]).each6 {|x| test_ok(x == [[6]])}
+IterTest.new([[7]]).each7 {|x| test_ok(x == 7)}
 IterTest.new([[8]]).each8 {|x| test_ok(x == [8])}
 
-IterTest.new([[0,0]]).each0 {|*x| test_ok(x == [0,0])}
-IterTest.new([[8,8]]).each8 {|*x| test_ok(x == [8,8])}
+IterTest.new([[0,0]]).each0 {|*x| test_ok(x == [[0,0]])}
+IterTest.new([[8,8]]).each8 {|*x| test_ok(x == [[8,8]])}
 
 def m0(v)
   v
Index: test/ruby/test_assignment.rb
===================================================================
RCS file: /src/ruby/test/ruby/test_assignment.rb,v
retrieving revision 1.10
diff -u -p -r1.10 test_assignment.rb
--- test/ruby/test_assignment.rb	10 Jul 2006 08:36:34 -0000	1.10
+++ test/ruby/test_assignment.rb	26 Sep 2006 16:52:04 -0000
@@ -90,22 +90,22 @@ class TestAssignment < Test::Unit::TestC
     def f; yield([*[1]]); end; f {|a| assert_equal([1], a)}; undef f
     def f; yield([*[1,2]]); end; f {|a| assert_equal([1,2], a)}; undef f
 
-    def f; yield(*[1]); end; f {|a| assert_equal([1], a)}; undef f
-    def f; yield(*[nil]); end; f {|a| assert_equal([nil], a)}; undef f
-    def f; yield(*[[]]); end; f {|a| assert_equal([[]], a)}; undef f
-    def f; yield(*[*[1]]); end; f {|a| assert_equal([1], a)}; undef f
+    def f; yield(*[1]); end; f {|a| assert_equal(1, a)}; undef f
+    def f; yield(*[nil]); end; f {|a| assert_equal(nil, a)}; undef f
+    def f; yield(*[[]]); end; f {|a| assert_equal([], a)}; undef f
+    def f; yield(*[*[1]]); end; f {|a| assert_equal(1, a)}; undef f
 
     def f; yield; end; f {|*a| assert_equal([], a)}; undef f
     def f; yield(nil); end; f {|*a| assert_equal([nil], a)}; undef f
     def f; yield(1); end; f {|*a| assert_equal([1], a)}; undef f
-    def f; yield([]); end; f {|*a| assert_equal([], a)}; undef f
-    def f; yield([1]); end; f {|*a| assert_equal([1], a)}; undef f
-    def f; yield([nil]); end; f {|*a| assert_equal([nil], a)}; undef f
-    def f; yield([[]]); end; f {|*a| assert_equal([[]], a)}; undef f
-    def f; yield([1,2]); end; f {|*a| assert_equal([1,2], a)}; undef f
-    def f; yield([*[]]); end; f {|*a| assert_equal([], a)}; undef f
-    def f; yield([*[1]]); end; f {|*a| assert_equal([1], a)}; undef f
-    def f; yield([*[1,2]]); end; f {|*a| assert_equal([1,2], a)}; undef f
+    def f; yield([]); end; f {|*a| assert_equal([[]], a)}; undef f
+    def f; yield([1]); end; f {|*a| assert_equal([[1]], a)}; undef f
+    def f; yield([nil]); end; f {|*a| assert_equal([[nil]], a)}; undef f
+    def f; yield([[]]); end; f {|*a| assert_equal([[[]]], a)}; undef f
+    def f; yield([1,2]); end; f {|*a| assert_equal([[1,2]], a)}; undef f
+    def f; yield([*[]]); end; f {|*a| assert_equal([[]], a)}; undef f
+    def f; yield([*[1]]); end; f {|*a| assert_equal([[1]], a)}; undef f
+    def f; yield([*[1,2]]); end; f {|*a| assert_equal([[1,2]], a)}; undef f
 
     def f; yield(*[]); end; f {|*a| assert_equal([], a)}; undef f
     def f; yield(*[1]); end; f {|*a| assert_equal([1], a)}; undef f
@@ -129,7 +129,7 @@ class TestAssignment < Test::Unit::TestC
     def f; yield(*[]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
     def f; yield(*[1]); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
     def f; yield(*[nil]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
-    def f; yield(*[[]]); end; f {|a,b,*c| assert_equal([[],nil,[]], [a,b,c])}; undef f
+    def f; yield(*[[]]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
     def f; yield(*[*[]]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
     def f; yield(*[*[1]]); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
     def f; yield(*[*[1,2]]); end; f {|a,b,*c| assert_equal([1,2,[]], [a,b,c])}; undef f
Index: test/ruby/test_iterator.rb
===================================================================
RCS file: /src/ruby/test/ruby/test_iterator.rb,v
retrieving revision 1.21
diff -u -p -r1.21 test_iterator.rb
--- test/ruby/test_iterator.rb	10 Jul 2006 08:36:34 -0000	1.21
+++ test/ruby/test_iterator.rb	26 Sep 2006 16:52:04 -0000
@@ -150,22 +150,22 @@ class TestIterator < Test::Unit::TestCas
     IterTest.new([1]).each1 {|x| assert_equal(1, x)}
     IterTest.new([2]).each2 {|x| assert_equal([2], x)}
     IterTest.new([4]).each4 {|x| assert_equal(4, x)}
-    IterTest.new([5]).each5 {|x| assert_equal([5], x)}
+    IterTest.new([5]).each5 {|x| assert_equal(5, x)}
     IterTest.new([6]).each6 {|x| assert_equal([6], x)}
     IterTest.new([8]).each8 {|x| assert_equal(8, x)}
 
     IterTest.new([[0]]).each0 {|x| assert_equal([0], x)}
-    IterTest.new([[1]]).each1 {|x| assert_equal(1, x)}
-    IterTest.new([[2]]).each2 {|x| assert_equal([2], x)}
+    IterTest.new([[1]]).each1 {|x| assert_equal([1], x)}
+    IterTest.new([[2]]).each2 {|x| assert_equal([[2]], x)}
     IterTest.new([[3]]).each3 {|x| assert_equal(3, x)}
     IterTest.new([[4]]).each4 {|x| assert_equal([4], x)}
     IterTest.new([[5]]).each5 {|x| assert_equal([5], x)}
-    IterTest.new([[6]]).each6 {|x| assert_equal([6], x)}
-    IterTest.new([[7]]).each7 {|x| assert_equal([7], x)}
+    IterTest.new([[6]]).each6 {|x| assert_equal([[6]], x)}
+    IterTest.new([[7]]).each7 {|x| assert_equal(7, x)}
     IterTest.new([[8]]).each8 {|x| assert_equal([8], x)}
 
-    IterTest.new([[0,0]]).each0 {|*x| assert_equal([0,0], x)}
-    IterTest.new([[8,8]]).each8 {|*x| assert_equal([8,8], x)}
+    IterTest.new([[0,0]]).each0 {|*x| assert_equal([[0,0]], x)}
+    IterTest.new([[8,8]]).each8 {|*x| assert_equal([[8,8]], x)}
   end
 
   def m(var)
@@ -359,6 +359,9 @@ class TestIterator < Test::Unit::TestCas
 
   class H
     def each
+      yield [:key, :value]
+    end
+    def each_pair
       yield :key, :value
     end
   end
@@ -366,8 +369,13 @@ class TestIterator < Test::Unit::TestCas
   def test_assoc_yield
     [{:key=>:value}, H.new].each {|h|
       h.each{|a| assert_equal([:key, :value], a)}
-      h.each{|*a| assert_equal([:key, :value], a)}
+      h.each{|a,| assert_equal(:key, a)}
+      h.each{|*a| assert_equal([[:key, :value]], a)}
       h.each{|k,v| assert_equal([:key, :value], [k,v])}
+      h.each_pair{|a| assert_equal(:key, a)}
+      h.each_pair{|a,| assert_equal(:key, a)}
+      h.each_pair{|*a| assert_equal([:key, :value], a)}
+      h.each_pair{|k,v| assert_equal([:key, :value], [k,v])}
     }
   end
 
-- 
[田中 哲][たなか あきら][Tanaka Akira]