From: Dominik Bathon Date: 2006-01-03T07:54:43+09:00 Subject: Re: Implicit block parameter? On Mon, 02 Jan 2006 21:32:57 +0100, Ross Bamford wrote: > Hi, > > Probably this has been considered before, but I'll ask anyway. I have also proposed this in October: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/162588 And it seems to have been proposed before. I have actually implemented it for ruby 1.9 lately (it should work similar for 1.8). It's just a small patch for eval.c: --- eval_org.c 2005-12-30 02:17:49.000000000 +0100 +++ eval.c 2006-01-02 23:25:46.000000000 +0100 @@ -4656,6 +4656,7 @@ rb_yield_0(VALUE val, VALUE self, VALUE NODE *cnode = ruby_current_node; int lambda = flags & YIELD_LAMBDA_CALL; int state; + VALUE it_val = Qnil; rb_need_block(); @@ -4675,8 +4676,10 @@ rb_yield_0(VALUE val, VALUE self, VALUE scope_vmode = (flags & YIELD_PUBLIC_DEF) ? SCOPE_PUBLIC : block->vmode; ruby_block = block->prev; if (block->flags & BLOCK_D_SCOPE) { + if (avalue && RARRAY(val)->len != 0) it_val = RARRAY(val)->ptr[0]; + if (!avalue && val != Qundef) it_val = val; /* put place holder for dynamic (in-block) local variables */ - ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars); + ruby_dyna_vars = new_dvar(0, it_val, block->dyna_vars); } else { /* FOR does not introduce new scope */ @@ -7596,6 +7599,15 @@ rb_exec_end_proc(void) ruby_safe_level = safe; } +static VALUE +rb_f_it(void) +{ + if (ruby_dyna_vars) { + if (ruby_dyna_vars->id == 0) return ruby_dyna_vars->val; + } + return Qnil; +} + void Init_eval(void) { @@ -7650,6 +7662,8 @@ Init_eval(void) rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */ rb_define_global_function("local_variables", rb_f_local_variables, 0); + rb_define_global_function("it", rb_f_it, 0); + rb_define_method(rb_mKernel, "send", rb_f_send, -1); rb_define_method(rb_mKernel, "__send__", rb_f_send, -1); rb_define_method(rb_mKernel, "funcall", rb_f_funcall, -1); This defines a global function #it that always returns the first block argument, it is not assignable. #it is available whether other block parameters are there or not. #it defaults to nil (if no arguments are given or if not in a block context. $ cat test_it.rb p (1..5).to_a.map { -it } %w[a b c].each { |x| p [x, it] } p it $ ./miniruby test_it.rb [-1, -2, -3, -4, -5] ["a", "a"] ["b", "b"] ["c", "c"] nil Dominik