List Info

Thread: Re: block args w/ defaults (updated)




Re: block args w/ defaults (updated)
user name
2008-05-27 08:07:44
2008/5/26 Radosław Bułat < radek.bulatgmail.com">radek.bulatgmail.com>:
Hey!

I've tried your patch and have some troubles.
I expected to this code:

def test
 yield
 yield(2)
end

test {|x=10| p x}

to print
10
2

but it prints
10
10

I&#39;ve tried also with &block but the same results.

At the end of this message is an update for this patch that fixes the above.&nbsp; I had to change vminshelper.c.  Apparently there is two completely separate functions for handling arguments (lambda vs. block/proc).  I updated the block/proc one for handling optional args. ; Seems like some refactoring should be done.

Also I updated the tests to call all of these with various blocks (instead of using lambda directly):

[method(:lambda), method(:proc), Proc.method(:new), lambda{|&amp;b|b}].each do |lam|
...
end

But worse problem was with irb. When I run irb1.9 (with this patch)
memory usage has jumped to > 50% (I have 2GB) and irb prompt didn't
even show. Don't you have this issue?
I haven't seen this, but I working off of r16568 (problem looks to start at r16615).

Here's the updated patch:


Index: sample/test.rb
===================================================================
--- sample/test.rb &nbsp;  (revision 16568)
+++ sample/test.rb &nbsp;  (working copy)
-296,6 +296,61
 test_ok(f.call([42,55]) == [[42,55]])
 test_ok(f.call(42,55) == [42,55])
&nbsp;
+[method(:lambda), method(:proc), Proc.method(:new), lambda{|&amp;b|b}].each do |lam|
+
+  ;  f = lam.call { |a, b=42, *c| [a,b,c] }
+ &nbsp;  test_ok(f.call(1 ; &nbsp; &nbsp; ) == [1,42,[&nbsp; ]] )
+ &nbsp;  test_ok(f.call(1,43&nbsp;  ) == [1,43,[&nbsp; ]] )
+ &nbsp;  test_ok(f.call(1,43,44) == [1,43,[44]] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |a, b=(a|16), *c, &block| [a,b,c,block&&;block[]] }
  ; test_ok(f.call(8 ; &nbsp; &nbsp; ) &nbsp; &nbsp; == [8,24,[&nbsp; ],nil] )
+ &nbsp;  test_ok(f.call(8,43&nbsp;  ) &nbsp; &nbsp; == [8,43,[&nbsp; ],nil] )
+ &nbsp;  test_ok(f.call(8,43,44) &nbsp; &nbsp; == [8,43,[44],nil] )
+ &nbsp;  test_ok(f.call(8 ; &nbsp; &nbsp; ) == [8,24,[&nbsp; ],45 ] )
  ; test_ok(f.call(8,43&nbsp;  ) == [8,43,[&nbsp; ],45 ] )
+ &nbsp;  test_ok(f.call(8,43,44) == [8,43,[44],45 ] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |a, b=42, *c, d| [a,b,c,d] }
+ &nbsp;  test_ok(f.call(1 ; &nbsp; &nbsp; ,99) == [1,42,[&nbsp; ],99] )
  ; test_ok(f.call(1,43&nbsp;  ,99) == [1,43,[&nbsp; ],99] )
+ &nbsp;  test_ok(f.call(1,43,44,99) == [1,43,[44],99] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |a, b=(a|16), &block| [a,b,block&&block[]] }
+ &nbsp;  test_ok(f.call(8 ;  ) &nbsp; &nbsp; == [8,24,nil] )
  ; test_ok(f.call(8,43)&nbsp;   ; == [8,43,nil] )
+ &nbsp;  test_ok(f.call(8 ;  ) == [8,24,45 ] )
+ &nbsp;  test_ok(f.call(8,43){45} == [8,43,45 ] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |a, b=42, d| [a,b,d] }
+ &nbsp;  test_ok(f.call(1 ;  ,99) == [1,42,99] )
  ; test_ok(f.call(1,43,99) == [1,43,99] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |b=42, *c, &block| [b,c,block&&block[]] }
+ &nbsp;  test_ok(f.call(   ;  ) &nbsp; &nbsp; == [42,[ ; ],nil] )
+ &nbsp;  test_ok(f.call(43&nbsp;  ) &nbsp; &nbsp; == [43,[ ; ],nil] )
  ; test_ok(f.call(43,44)  ; &nbsp; == [43,[44],nil] )
+ &nbsp;  test_ok(f.call(   ;  ) == [42,[ ; ],45 ] )
+ &nbsp;  test_ok(f.call(43&nbsp;  ) == [43,[ ; ],45 ] )
+ &nbsp;  test_ok(f.call(43,44) == [43,[44],45 ] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |b=42, *c, d| [b,c,d] }
+ &nbsp;  test_ok(f.call(   ; &nbsp; 99) == [42,[ ; ],99] )
+ &nbsp;  test_ok(f.call(43&nbsp;  ,99) == [43,[ ; ],99] )
+ &nbsp;  test_ok(f.call(43,44,99) == [43,[44],99] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |b=42, &block| [b,block&amp;&block[]] }
  ; test_ok(f.call(  ) &nbsp; &nbsp; == [42,nil] )
+ &nbsp;  test_ok(f.call(43)&nbsp; &nbsp;  == [43,nil] )
+ &nbsp;  test_ok(f.call(  ) == [42,45 ] )
+ &nbsp;  test_ok(f.call(43){45} == [43,45 ] )
+ &nbsp; 
+ &nbsp;  f = lam.call { |b=42, d| [b,d] }
  ; test_ok(f.call(   99) == [42,99] )
+ &nbsp;  test_ok(f.call(43,99) == [43,99] )
+
+end
+
 a,=*[1]
 test_ok(a == 1)
 a,=*[[1]]
Index: parse.y
===================================================================
--- parse.y&nbsp; &nbsp; (revision 16568)
+++ parse.y&nbsp; &nbsp; (working copy)
-666,6 +666,7
 %type <node&gt; open_args paren_args opt_paren_args
 %type <node&gt; command_args aref_args opt_block_arg block_arg var_ref var_lhs
&nbsp;%type <node&gt; mrhs superclass block_call block_command
+%type <node&gt; f_block_optarg f_block_opt
 %type <node&gt; f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
&nbsp;%type <node&gt; assoc_list assocs assoc undef_list backref string_dvar for_var
&nbsp;%type <node&gt; block_param opt_block_param block_param_def f_opt
-3169,9 +3170,41
 &nbsp; &nbsp;  &nbsp;   &nbsp;  }
 &nbsp; &nbsp;  &nbsp;  ;
 
-block_param  ;  : f_arg ','; f_rest_arg opt_f_block_arg
+block_param&nbsp; &nbsp; : f_arg ','; f_block_optarg ','; f_rest_arg opt_f_block_arg
&nbsp; &nbsp;   &nbsp;   &nbsp;  {
 &nbsp; &nbsp;  &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args($1, $3, $5, 0, $6);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
+  ;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  | f_arg ','; f_block_optarg ','; f_rest_arg ','; f_arg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args($1, $3, $5, $7, $8);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new($1, $3, $5, $7, escape_Qundef($8));
+  ;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  | f_arg ','; f_block_optarg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args($1, $3, 0, 0, $4);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
+  ;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
  ;  &nbsp;  | f_arg ','; f_block_optarg ','; f_arg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args($1, $3, 0, $5, $6);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
+ &nbsp;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   ; &nbsp; &nbsp; &nbsp; &nbsp;   | f_arg ','; f_rest_arg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
&nbsp; &nbsp;   &nbsp;   &nbsp;  $$ = new_args($1, 0, $3, 0, $4);
 ; &nbsp;   &nbsp;   &nbsp;  /*%
   ;   &nbsp;   &nbsp;  $$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
-3202,6 +3235,38
 &nbsp; &nbsp;  &nbsp;   &nbsp;  $$ = params_new($1, Qnil,Qnil, Qnil, escape_Qundef($2));
&nbsp;   ;  &nbsp;   &nbsp;  %*/
   ;   &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  | f_block_optarg ','; f_rest_arg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
  ;  &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args(0, $1, $3, 0, $4);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
+  ;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  | f_block_optarg ','; f_rest_arg ','; f_arg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args(0, $1, $3, $5, $6);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
+  ;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  | f_block_optarg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args(0, $1, 0, 0, $2);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
  ;  &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
  ;  &nbsp;  | f_block_optarg ','; f_arg opt_f_block_arg
+&nbsp; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = new_args(0, $1, 0, $3, $4);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
+ &nbsp;   &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
 &nbsp; &nbsp;  &nbsp;  | f_rest_arg opt_f_block_arg
 ; &nbsp;   &nbsp;   &nbsp;  {
 &nbsp; &nbsp;  &nbsp;   &nbsp;  /*%%%*/
-4302,6 +4367,44
 &nbsp; &nbsp;  &nbsp;   &nbsp;  }
 &nbsp; &nbsp;  &nbsp;  ;
 
+f_block_opt  ;  : tIDENTIFIER '='; primary_value
; &nbsp;  &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  if (!is_local_id($1))
+&nbsp;    &nbsp;   &nbsp;   &nbsp;  yyerror(&quot;formal argument must be local variable&quot;);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  shadowing_lvar($1);
+  ;   &nbsp;   &nbsp;  arg_var($1);
  ;  &nbsp;   &nbsp;  $$ = NEW_OPT_ARG(0, assignable($1, $3));
+&nbsp; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = rb_assoc_new($1, $3);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  ;
+
+f_block_optarg&nbsp; &nbsp; : f_block_opt
+ &nbsp;   &nbsp;   &nbsp;  {
  ;  &nbsp;   &nbsp;  /*%%%*/
+&nbsp;    &nbsp;   &nbsp;  $$ = $1;
; &nbsp;  &nbsp;   &nbsp;  /*%
; &nbsp;  &nbsp;   &nbsp;  $$ = rb_ary_new3(1, $1);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  | f_block_optarg ','; f_block_opt
+ &nbsp;   &nbsp;   &nbsp;  {
+ &nbsp;   &nbsp;   &nbsp;  /*%%%*/
+  ;   &nbsp;   &nbsp;  NODE *opts = $1;
+
+&nbsp; &nbsp;  &nbsp;   &nbsp;  while (opts->nd_next) {
+ &nbsp;   &nbsp;   &nbsp;   &nbsp;  opts = opts->nd_next;
+&nbsp; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;   &nbsp;  opts->nd_next = $3;
; &nbsp;  &nbsp;   &nbsp;  $$ = $1;
; &nbsp;  &nbsp;   &nbsp;  /*%
+&nbsp; &nbsp;  &nbsp;   &nbsp;  $$ = rb_ary_push($1, $3);
+&nbsp; &nbsp;  &nbsp;   &nbsp;  %*/
; &nbsp;  &nbsp;   &nbsp;  }
+ &nbsp;   &nbsp;  ;
+
 f_optarg&nbsp; &nbsp; : f_opt
&nbsp; &nbsp;   &nbsp;   &nbsp;  {
 &nbsp; &nbsp;  &nbsp;   &nbsp;  /*%%%*/
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c   ; (revision 16568)
+++ vm_insnhelper.c   ; (working copy)
-699,7 +699,8
 &nbsp; &nbsp; else {
 &nbsp; &nbsp; int i;
 &nbsp;   int argc = orig_argc;
- &nbsp;  const int m = iseq->argc;
; &nbsp; int m = iseq->argc;
+&nbsp; &nbsp; int opt_pc = 0;
 
  ; &nbsp; th->mark_stack_len = argc;
&nbsp;
-719,18 +720,39
 &nbsp; &nbsp;  &nbsp;  MEMCPY(argv, RARRAY_PTR(ary), VALUE, argc);
&nbsp; &nbsp;  }
 
+  ; &nbsp; &nbsp;  if (iseq->arg_opts) {
+ &nbsp;   ; &nbsp; &nbsp; &nbsp; const int opts = iseq->arg_opts - 1 /* no opt */;
+&nbsp; &nbsp; &nbsp; &nbsp;   ;  int overrides = argc-(m + iseq->arg_post_len);
+ &nbsp;   ; &nbsp; &nbsp; &nbsp; if (overrides > opts) overrides = opts;
+&nbsp; &nbsp; &nbsp;   ; &nbsp;  else if (overrides < 0) overrides = 0;
  ; &nbsp; &nbsp; &nbsp; &nbsp; opt_pc = iseq->arg_opt_table[overrides];
  ; &nbsp; &nbsp; &nbsp; &nbsp; m += overrides;
+ &nbsp; &nbsp; &nbsp;  }
+
   ;  for (i=argc; i<m; i++) {
 &nbsp; &nbsp;  &nbsp;  argv[i] = Qnil;
&nbsp; &nbsp;  }
 
&nbsp;   ; if (iseq->arg_rest == -1) {
- &nbsp;   &nbsp;  if (m < argc) {
+ &nbsp;   &nbsp;  if ( (m + iseq->arg_post_len) < argc) {
 &nbsp;    &nbsp;  /*
 &nbsp;    &nbsp;   * yield 1, 2
 &nbsp; &nbsp;  &nbsp;   * => {|a|} # truncate
&nbsp;   ;  &nbsp;   */
-  ;   &nbsp;  th->mark_stack_len = argc = m;
  ;  &nbsp;  th->mark_stack_len = argc = m + iseq->arg_post_len;
 &nbsp; &nbsp;  &nbsp;  }
  ; &nbsp; &nbsp; &nbsp; &nbsp; if (iseq->arg_post_len) {
+ &nbsp;   &nbsp;  int len = iseq->arg_post_len;
+ &nbsp;   &nbsp;  int start = iseq->arg_post_start;
  ;  &nbsp;  int rsize = argc > m ? argc - m : 0;
  ;  &nbsp;  int psize = rsize;
+
+ &nbsp;   &nbsp;  MEMMOVE(&amp;argv[start], &argv[argc - psize], VALUE, psize);
+
+ &nbsp;   &nbsp;  for (i=psize; i<len; i++) {
+ &nbsp;   &nbsp;   &nbsp;  argv[start + i] = Qnil;
+&nbsp; &nbsp;  &nbsp;  }
+ &nbsp;   ; &nbsp; &nbsp; &nbsp; }
 &nbsp; &nbsp; }
 &nbsp; &nbsp; else {
 &nbsp;    &nbsp;  int r = iseq->arg_rest;
-754,7 +776,7
 &nbsp; &nbsp;  &nbsp;  }
 
&nbsp;   ;  &nbsp;  /* copy post argument */
  ;  &nbsp;  MEMMOVE(&amp;argv[start], &argv[r + rsize - psize], VALUE, psize);
+&nbsp;    &nbsp;  MEMMOVE(&amp;argv[start], &argv[argc - psize], VALUE, psize);
&nbsp;
 ; &nbsp;   &nbsp;  for (i=psize; i<len; i++) {
 &nbsp; &nbsp;  &nbsp;   &nbsp;  argv[start + i] = Qnil;
-791,7 +813,7
 &nbsp; &nbsp; }
 
&nbsp;   ; th->mark_stack_len = 0;
  ; return 0;
  ; return opt_pc;
&nbsp; &nbsp;  }
 }
 

Re: block args w/ defaults (updated)
user name
2008-05-27 09:10:13
Could you send this patch as attachment please? When I copy
it from
mail there are some white space issue and patch couldn't be
applied
automatically (the same was with previous but attached patch
worked
for me).


-- 
Radosław Bułat

http://radarek.jogger.pl
- mój blog
Re: block args w/ defaults (updated)
user name
2008-05-27 20:44:00
2008/5/27 Radosław Bułat < radek.bulatgmail.com">radek.bulatgmail.com>:
Could you send this patch as attachment please? When I copy it from
mail there are some white space issue and patch couldn';t be applied
automatically (the same was with previous but attached patch worked
for me).

I';m attaching it as a .txt file so that it is viewable (gmail always uses base64 for .patch).

  
Re: block args w/ defaults (updated)
user name
2008-05-27 21:04:40
2008/5/27 Radoslaw Bulat <radek.bulatgmail.com>:
>
> Could you send this patch as attachment please? When I
copy it from
> mail there are some white space issue and patch
couldn't be applied
> automatically (the same was with previous but attached
patch worked
> for me).

Another try.  This time telling gmail to use plain text for
composing.
 I'm assuming your name was causing the whole message to be
base64
encoded making it unreadable on the ruby-core archive.

  
Re: block args w/ defaults (updated)
country flaguser name
United States
2008-05-27 23:54:06
Eric Mahurin wrote:
> 2008/5/26 Rados�aw Bu�at <radek.bulatgmail.com>:
>> I've tried your patch and have some troubles.
>> I expected to this code:
>>
>> def test
>>  yield
>>  yield(2)
>> end
>>
>> test {|x=10| p x}
>>
>> to print
>> 10
>> 2
>>
>> but it prints
>> 10
>> 10
>>
>> I've tried also with &block but the same
results.
> 
> At the end of this message is an update for this patch
that fixes the
> above.

I confirm that this updated patch fixes the above example:

 >> def test
 >>   yield
 >>   yield 2
 >> end
=> nil

 >> test {|x=10| p x}
10
2
=> 2

 >> f = lambda {|x=8| p x}
=> #<Proc:0x83af7c0(irb):12 (lambda)>

 >> test &f
8
2
=> 2

 >> def test2 &b
 >>   p :b => b
 >>   b.call 15
 >> end
=> nil

 >> test2 {|x=5,y=10,z=15| p x: x, y: y, z: z}
{:b=>#<Proc:0x83bd26c(irb):11>}
{=>
15, :y=>10, :z=>15}
=> {=>
15, :y=>10, :z=>15}



[1-5]

about | contact  Other archives ( Real Estate discussion Medical topics )