mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* eval.c (rb_yield_0, proc_invoke, proc_arity): allow passing a block
to a Proc. [ruby-dev:23533] * parse.y (block_par, block_var): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6402 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									1efe963c7a
								
							
						
					
					
						commit
						82572952ec
					
				
					 5 changed files with 186 additions and 28 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,10 @@
 | 
			
		|||
Tue May 25 11:54:13 2004  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* eval.c (rb_yield_0, proc_invoke, proc_arity): allow passing a block
 | 
			
		||||
	  to a Proc.  [ruby-dev:23533]
 | 
			
		||||
 | 
			
		||||
	* parse.y (block_par, block_var): ditto.
 | 
			
		||||
 | 
			
		||||
Tue May 25 01:50:17 2004  GOTOU Yuuzou  <gotoyuzo@notwork.org>
 | 
			
		||||
 | 
			
		||||
	* ext/openssl/ossl_asn1.c (ossl_i2d_ASN1_TYPE, ossl_ASN1_TYPE_free):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										63
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										63
									
								
								eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4569,7 +4569,7 @@ rb_yield_0(val, self, klass, flags, avalue)
 | 
			
		|||
    VALUE val, self, klass;	/* OK */
 | 
			
		||||
    int flags, avalue;
 | 
			
		||||
{
 | 
			
		||||
    NODE *node;
 | 
			
		||||
    NODE *node, *var;
 | 
			
		||||
    volatile VALUE result = Qnil;
 | 
			
		||||
    volatile VALUE old_cref;
 | 
			
		||||
    volatile VALUE old_wrapper;
 | 
			
		||||
| 
						 | 
				
			
			@ -4612,27 +4612,35 @@ rb_yield_0(val, self, klass, flags, avalue)
 | 
			
		|||
	self = block->self;
 | 
			
		||||
    }
 | 
			
		||||
    node = block->body;
 | 
			
		||||
    var = block->var;
 | 
			
		||||
 | 
			
		||||
    if (block->var) {
 | 
			
		||||
    if (var) {
 | 
			
		||||
	PUSH_TAG(PROT_NONE);
 | 
			
		||||
	if ((state = EXEC_TAG()) == 0) {
 | 
			
		||||
	    if (block->var == (NODE*)1) { /* no parameter || */
 | 
			
		||||
	    NODE *bvar = NULL;
 | 
			
		||||
	  block_var:
 | 
			
		||||
	    if (var == (NODE*)1) { /* no parameter || */
 | 
			
		||||
		if (lambda && RARRAY(val)->len != 0) {
 | 
			
		||||
		    rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
 | 
			
		||||
			     RARRAY(val)->len);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	    else if (block->var == (NODE*)2) {
 | 
			
		||||
	    else if (var == (NODE*)2) {
 | 
			
		||||
		if (TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
 | 
			
		||||
		    rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
 | 
			
		||||
			     RARRAY(val)->len);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	    else if (nd_type(block->var) == NODE_MASGN) {
 | 
			
		||||
	    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_MASGN) {
 | 
			
		||||
		if (!avalue) {
 | 
			
		||||
		    val = svalue_to_mrhs(val, block->var->nd_head);
 | 
			
		||||
		    val = svalue_to_mrhs(val, var->nd_head);
 | 
			
		||||
		}
 | 
			
		||||
		massign(self, block->var, val, lambda);
 | 
			
		||||
		massign(self, var, val, lambda);
 | 
			
		||||
	    }
 | 
			
		||||
	    else {
 | 
			
		||||
		int len = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -4653,13 +4661,21 @@ rb_yield_0(val, self, klass, flags, avalue)
 | 
			
		|||
		    val = Qnil;
 | 
			
		||||
		  multi_values:
 | 
			
		||||
		    {
 | 
			
		||||
			ruby_current_node = block->var;
 | 
			
		||||
			ruby_current_node = var;
 | 
			
		||||
			rb_warn("multiple values for a block parameter (%d for 1)\n\tfrom %s:%d",
 | 
			
		||||
				len, cnode->nd_file, nd_line(cnode));
 | 
			
		||||
			ruby_current_node = cnode;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
		assign(self, block->var, val, lambda);
 | 
			
		||||
		assign(self, var, val, lambda);
 | 
			
		||||
	    }
 | 
			
		||||
	    if (bvar) {
 | 
			
		||||
		VALUE blk;
 | 
			
		||||
		if (flags & YIELD_PROC_CALL)
 | 
			
		||||
		    blk = block->block_obj;
 | 
			
		||||
		else
 | 
			
		||||
		    blk = rb_block_proc();
 | 
			
		||||
		assign(self, bvar, blk, 0);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	POP_TAG();
 | 
			
		||||
| 
						 | 
				
			
			@ -8021,13 +8037,12 @@ proc_invoke(proc, args, self, klass)
 | 
			
		|||
    volatile VALUE old_wrapper = ruby_wrapper;
 | 
			
		||||
    struct RVarmap * volatile old_dvars = ruby_dyna_vars;
 | 
			
		||||
    volatile int pcall, avalue = Qtrue;
 | 
			
		||||
    VALUE bvar = Qnil;
 | 
			
		||||
 | 
			
		||||
    if (rb_block_given_p() && ruby_frame->last_func) {
 | 
			
		||||
	if (klass != ruby_frame->last_class)
 | 
			
		||||
	    klass = rb_obj_class(proc);
 | 
			
		||||
	rb_warning("block for %s#%s is useless",
 | 
			
		||||
		   rb_class2name(klass),
 | 
			
		||||
		   rb_id2name(ruby_frame->last_func));
 | 
			
		||||
	bvar = rb_block_proc();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Data_Get_Struct(proc, struct BLOCK, data);
 | 
			
		||||
| 
						 | 
				
			
			@ -8043,6 +8058,7 @@ proc_invoke(proc, args, self, klass)
 | 
			
		|||
    /* PUSH BLOCK from data */
 | 
			
		||||
    old_block = ruby_block;
 | 
			
		||||
    _block = *data;
 | 
			
		||||
    _block.block_obj = bvar;
 | 
			
		||||
    if (self != Qundef) _block.frame.self = self;
 | 
			
		||||
    if (klass) _block.frame.last_class = klass;
 | 
			
		||||
    ruby_block = &_block;
 | 
			
		||||
| 
						 | 
				
			
			@ -8053,7 +8069,8 @@ proc_invoke(proc, args, self, klass)
 | 
			
		|||
    state = EXEC_TAG();
 | 
			
		||||
    if (state == 0) {
 | 
			
		||||
	proc_set_safe_level(proc);
 | 
			
		||||
	result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0, pcall, avalue);
 | 
			
		||||
	result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0,
 | 
			
		||||
			    pcall | YIELD_PROC_CALL, avalue);
 | 
			
		||||
    }
 | 
			
		||||
    else if (TAG_DST()) {
 | 
			
		||||
	result = prot_tag->retval;
 | 
			
		||||
| 
						 | 
				
			
			@ -8157,30 +8174,36 @@ proc_arity(proc)
 | 
			
		|||
    VALUE proc;
 | 
			
		||||
{
 | 
			
		||||
    struct BLOCK *data;
 | 
			
		||||
    NODE *list;
 | 
			
		||||
    NODE *var, *list;
 | 
			
		||||
    int n;
 | 
			
		||||
 | 
			
		||||
    Data_Get_Struct(proc, struct BLOCK, data);
 | 
			
		||||
    if (data->var == 0) {
 | 
			
		||||
    var = data->var;
 | 
			
		||||
    if (var == 0) {
 | 
			
		||||
	if (data->body && nd_type(data->body) == NODE_IFUNC &&
 | 
			
		||||
	    data->body->nd_cfnc == bmcall) {
 | 
			
		||||
	    return method_arity(data->body->nd_tval);
 | 
			
		||||
	}
 | 
			
		||||
	return INT2FIX(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (data->var == (NODE*)1) return INT2FIX(0);
 | 
			
		||||
    if (data->var == (NODE*)2) return INT2FIX(0);
 | 
			
		||||
    switch (nd_type(data->var)) {
 | 
			
		||||
    if (var == (NODE*)1) return INT2FIX(0);
 | 
			
		||||
    if (var == (NODE*)2) return INT2FIX(0);
 | 
			
		||||
    if (nd_type(var) == NODE_BLOCK_ARG) {
 | 
			
		||||
	var = var->nd_args;
 | 
			
		||||
	if (var == (NODE*)1) return INT2FIX(0);
 | 
			
		||||
	if (var == (NODE*)2) return INT2FIX(0);
 | 
			
		||||
    }
 | 
			
		||||
    switch (nd_type(var)) {
 | 
			
		||||
      default:
 | 
			
		||||
	return INT2FIX(1);
 | 
			
		||||
      case NODE_MASGN:
 | 
			
		||||
	list = data->var->nd_head;
 | 
			
		||||
	list = var->nd_head;
 | 
			
		||||
	n = 0;
 | 
			
		||||
	while (list) {
 | 
			
		||||
	    n++;
 | 
			
		||||
	    list = list->nd_next;
 | 
			
		||||
	}
 | 
			
		||||
	if (data->var->nd_args) return INT2FIX(-n-1);
 | 
			
		||||
	if (var->nd_args) return INT2FIX(-n-1);
 | 
			
		||||
	return INT2FIX(n);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										75
									
								
								parse.y
									
										
									
									
									
								
							
							
						
						
									
										75
									
								
								parse.y
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -179,6 +179,8 @@ static void top_local_setup();
 | 
			
		|||
#define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
 | 
			
		||||
#define nd_nest u3.id
 | 
			
		||||
 | 
			
		||||
#define NEW_BLOCK_VAR(b, v) NEW_NODE(NODE_BLOCK_PASS, 0, b, v)
 | 
			
		||||
 | 
			
		||||
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
 | 
			
		||||
   for instance).  This is too low for Ruby to parse some files, such as
 | 
			
		||||
   date/format.rb, therefore bump the value up to at least Bison's default. */
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +264,8 @@ static void top_local_setup();
 | 
			
		|||
%type <node> mrhs superclass block_call block_command
 | 
			
		||||
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
 | 
			
		||||
%type <node> assoc_list assocs assoc kwargs undef_list backref string_dvar
 | 
			
		||||
%type <node> block_var opt_block_var brace_block cmd_brace_block do_block lhs none
 | 
			
		||||
%type <node> for_var block_var opt_block_var block_par
 | 
			
		||||
%type <node> brace_block cmd_brace_block do_block lhs none
 | 
			
		||||
%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
 | 
			
		||||
%type <id>   fitem variable sym symbol operation operation2 operation3
 | 
			
		||||
%type <id>   cname fname op f_rest_arg
 | 
			
		||||
| 
						 | 
				
			
			@ -1589,7 +1592,7 @@ primary		: literal
 | 
			
		|||
		    {
 | 
			
		||||
			$$ = $4;
 | 
			
		||||
		    }
 | 
			
		||||
		| kFOR block_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
 | 
			
		||||
		| kFOR for_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
 | 
			
		||||
		  compstmt
 | 
			
		||||
		  kEND
 | 
			
		||||
		    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1739,10 +1742,76 @@ opt_else	: none
 | 
			
		|||
		    }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
block_var	: lhs
 | 
			
		||||
for_var 	: lhs
 | 
			
		||||
		| mlhs
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
block_par	: mlhs_item
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_LIST($1);
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ',' mlhs_item
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = list_append($1, $3);
 | 
			
		||||
		    }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
block_var	: block_par
 | 
			
		||||
		    {
 | 
			
		||||
			if ($1->nd_alen == 1) {
 | 
			
		||||
			    $$ = $1->nd_head;
 | 
			
		||||
			    rb_gc_force_recycle((VALUE)$1);
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
			    $$ = NEW_MASGN($1, 0);
 | 
			
		||||
			}
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ','
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_MASGN($1, 0);
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ',' tAMPER lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_BLOCK_VAR($4, NEW_MASGN($1, 0));
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ',' tSTAR lhs ',' tAMPER lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_BLOCK_VAR($7, NEW_MASGN($1, $4));
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ',' tSTAR ',' tAMPER lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_BLOCK_VAR($6, NEW_MASGN($1, -1));
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ',' tSTAR lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_MASGN($1, $4);
 | 
			
		||||
		    }
 | 
			
		||||
		| block_par ',' tSTAR
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_MASGN($1, -1);
 | 
			
		||||
		    }
 | 
			
		||||
		| tSTAR lhs ',' tAMPER lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_BLOCK_VAR($5, NEW_MASGN(0, $2));
 | 
			
		||||
		    }
 | 
			
		||||
		| tSTAR ',' tAMPER lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_BLOCK_VAR($4, NEW_MASGN(0, -1));
 | 
			
		||||
		    }
 | 
			
		||||
		| tSTAR lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_MASGN(0, $2);
 | 
			
		||||
		    }
 | 
			
		||||
		| tSTAR
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_MASGN(0, -1);
 | 
			
		||||
		    }
 | 
			
		||||
		| tAMPER lhs
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_BLOCK_VAR($2, (NODE*)1);
 | 
			
		||||
		    }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
opt_block_var	: none
 | 
			
		||||
		| '|' /* none */ '|'
 | 
			
		||||
		    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,30 @@ a = *[*[]]; test_ok(a == nil)
 | 
			
		|||
a = *[*[1]]; test_ok(a == 1)
 | 
			
		||||
a = *[*[1,2]]; test_ok(a == [1,2])
 | 
			
		||||
 | 
			
		||||
a, = nil; test_ok(a == nil)
 | 
			
		||||
a, = 1; test_ok(a == 1)
 | 
			
		||||
a, = []; test_ok(a == nil)
 | 
			
		||||
a, = [1]; test_ok(a == 1)
 | 
			
		||||
a, = [nil]; test_ok(a == nil)
 | 
			
		||||
a, = [[]]; test_ok(a == [])
 | 
			
		||||
a, = 1,2; test_ok(a == 1)
 | 
			
		||||
a, = [1,2]; test_ok(a == 1)
 | 
			
		||||
a, = [*[]]; test_ok(a == nil)
 | 
			
		||||
a, = [*[1]]; test_ok(a == 1)
 | 
			
		||||
a, = *[1,2]; test_ok(a == 1)
 | 
			
		||||
a, = [*[1,2]]; test_ok(a == 1)
 | 
			
		||||
 | 
			
		||||
a, = *nil; test_ok(a == nil)
 | 
			
		||||
a, = *1; test_ok(a == 1)
 | 
			
		||||
a, = *[]; test_ok(a == nil)
 | 
			
		||||
a, = *[1]; test_ok(a == 1)
 | 
			
		||||
a, = *[nil]; test_ok(a == nil)
 | 
			
		||||
a, = *[[]]; test_ok(a == [])
 | 
			
		||||
a, = *[1,2]; test_ok(a == 1)
 | 
			
		||||
a, = *[*[]]; test_ok(a == nil)
 | 
			
		||||
a, = *[*[1]]; test_ok(a == 1)
 | 
			
		||||
a, = *[*[1,2]]; test_ok(a == 1)
 | 
			
		||||
 | 
			
		||||
*a = nil; test_ok(a == [nil])
 | 
			
		||||
*a = 1; test_ok(a == [1])
 | 
			
		||||
*a = []; test_ok(a == [[]])
 | 
			
		||||
| 
						 | 
				
			
			@ -126,6 +150,27 @@ def f; yield *[nil]; end; f {|a| test_ok(a == nil)}
 | 
			
		|||
def f; yield *[[]]; end; f {|a| test_ok(a == [])}
 | 
			
		||||
def f; yield *[*[1]]; 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)}
 | 
			
		||||
def f; yield 1; end; f {|a,| test_ok(a == 1)}
 | 
			
		||||
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 *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 == 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 == [])}
 | 
			
		||||
def f; yield nil; end; f {|*a| test_ok(a == [nil])}
 | 
			
		||||
def f; yield 1; end; f {|*a| test_ok(a == [1])}
 | 
			
		||||
| 
						 | 
				
			
			@ -1000,15 +1045,21 @@ 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])}
 | 
			
		||||
 | 
			
		||||
def m
 | 
			
		||||
  test_ok(block_given?)
 | 
			
		||||
def m0(v)
 | 
			
		||||
  v
 | 
			
		||||
end
 | 
			
		||||
m{p 'test'}
 | 
			
		||||
 | 
			
		||||
def m1
 | 
			
		||||
  m0(block_given?)
 | 
			
		||||
end
 | 
			
		||||
test_ok(m1{p 'test'})
 | 
			
		||||
test_ok(!m1)
 | 
			
		||||
 | 
			
		||||
def m
 | 
			
		||||
  test_ok(block_given?,&proc{})
 | 
			
		||||
  m0(block_given?,&proc{})
 | 
			
		||||
end
 | 
			
		||||
m{p 'test'}
 | 
			
		||||
test_ok(m1{p 'test'})
 | 
			
		||||
test_ok(!m1)
 | 
			
		||||
 | 
			
		||||
class C
 | 
			
		||||
  include Enumerable
 | 
			
		||||
| 
						 | 
				
			
			@ -1079,6 +1130,9 @@ test_ok(get_block(&lambda).class == Proc)
 | 
			
		|||
test_ok(Proc.new{|a,| a}.call(1,2,3) == 1)
 | 
			
		||||
argument_test(true, Proc.new{|a,|}, 1,2)
 | 
			
		||||
 | 
			
		||||
test_ok(Proc.new{|&b| b.call(10)}.call {|x| x} == 10)
 | 
			
		||||
test_ok(Proc.new{|a,&b| b.call(a)}.call(12) {|x| x} == 12)
 | 
			
		||||
 | 
			
		||||
def test_return1
 | 
			
		||||
  Proc.new {
 | 
			
		||||
    return 55
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,4 +86,9 @@ class TestProc < Test::Unit::TestCase
 | 
			
		|||
    b = lambda {}
 | 
			
		||||
    assert_not_equal(a, b)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_block_par
 | 
			
		||||
    assert_equal(10, Proc.new{|&b| b.call(10)}.call {|x| x})
 | 
			
		||||
    assert_equal(12, Proc.new{|a,&b| b.call(a)}.call(12) {|x| x})
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue