List Info

Thread: block args w/ defaults (was Re: resolving lambda | ambiguity)




block args w/ defaults (was Re: resolving lambda | ambiguity)
user name
2008-05-24 17:27:29
On Sat, May 24, 2008 at 4:06 PM, Eric Mahurin < eric.mahuringmail.com">eric.mahuringmail.com> wrote:
On Fri, May 23, 2008 at 7:18 AM, ts < decouxmoulon.inra.fr" target="_blank">decouxmoulon.inra.fr> wrote:
Eric Mahurin wrote:
&gt; Is there any reason this idea couldn';t be applied to head?

 Try it on your personal version.

Guy Decoux

Here is a patch for handling optional args for blocks using this simple idea - use a "primary_value&quot; instead of "arg_value" for the default values.&nbsp; I simply did some cutting and pasting for the argument definitions for "def&quot; and changed "arg_value" to "primary_value&quot;.  It worked on the first try!  Spent more time writing tests (included) than adding the new functionality.

Matz, any chance this could be integrated for a trial period at least?&nbsp; It shouldn9;t cause any compatibility issues.

For some reason, gmail attached my patch with base64 encoding.&nbsp; A simple cut-n-paste of the patch is below.&nbsp; Also here would be a reasonable ChangeLog entry:

* parse.y (block_param) : added alternatives for allowing arguments with defaults.&nbsp; These are identical to what is in f_args except f_block_optarg is used instead of f_optarg.&nbsp; f_block_optarg is the same as f_optarg except primary_value is used instead of arg_value.
* sample/test.rb (assignment) : tested these new alternatives with defaults for arguments.


Index: sample/test.rb
===================================================================
--- sample/test.rb &nbsp;  (revision 16568)
+++ sample/test.rb &nbsp;  (working copy)
-296,6 +296,64
 test_ok(f.call([42,55]) == [[42,55]])
 test_ok(f.call(42,55) == [42,55])
&nbsp;
+f = lambda { |a, b=42, *c| [a,b,c] }
+test_ok(f.call(1&nbsp; &nbsp;   ) == [1,42,[&nbsp; ]] )
+test_ok(f.call(1,43 &nbsp; ) == [1,43,[&nbsp; ]] )
+test_ok(f.call(1,43,44) == [1,43,[44]] )
+
+f = lambda { |a, b=(a|16), *c, &block| [a,b,c,block&&;block[]] }
+test_ok(f.call(8&nbsp; &nbsp;   ) &nbsp; &nbsp; == [8,24,[&nbsp; ],nil] )
+test_ok(f.call(8,43 &nbsp; ) &nbsp; &nbsp; == [8,43,[&nbsp; ],nil] )
+test_ok(f.call(8,43,44)   ;  == [8,43,[44],nil] )
+test_ok(f.call(8&nbsp; &nbsp;   ) == [8,24,[&nbsp; ],45 ] )
+test_ok(f.call(8,43 &nbsp; ) == [8,43,[&nbsp; ],45 ] )
+test_ok(f.call(8,43,44) == [8,43,[44],45 ] )
+
+f = lambda { |a, b=42, *c, d| [a,b,c,d] }
+test_ok(f.call(1&nbsp; &nbsp;   ,99) == [1,42,[&nbsp; ],99] )
+test_ok(f.call(1,43 &nbsp; ,99) == [1,43,[&nbsp; ],99] )
+test_ok(f.call(1,43,44,99) == [1,43,[44],99] )
+
+f = lambda { |a, b=(a|16), &block| [a,b,block&&block[]] }
+test_ok(f.call(8  ; ) &nbsp; &nbsp; == [8,24,nil] )
+test_ok(f.call(8,43) &nbsp; &nbsp; == [8,43,nil] )
+test_ok(f.call(8,43) &nbsp; &nbsp; == [8,43,nil] )
+test_ok(f.call(8&nbsp;  ) == [8,24,45 ] )
+test_ok(f.call(8,43) == [8,43,45 ] )
+test_ok(f.call(8,43) == [8,43,45 ] )
+
+f = lambda { |a, b=42, d| [a,b,d] }
+test_ok(f.call(1&nbsp;  ,99) == [1,42,99] )
+test_ok(f.call(1,43,99) == [1,43,99] )
+test_ok(f.call(1,43,99) == [1,43,99] )
+
+f = lambda { |b=42, *c, &block| [b,c,block&&block[]] }
+test_ok(f.call(&nbsp; &nbsp;  ) &nbsp; &nbsp; == [42,[ ; ],nil] )
+test_ok(f.call(43&nbsp;  ) &nbsp; &nbsp; == [43,[ ; ],nil] )
+test_ok(f.call(43,44) &nbsp; &nbsp; == [43,[44],nil] )
+test_ok(f.call(&nbsp; &nbsp;  ) == [42,[ ; ],45 ] )
+test_ok(f.call(43 &nbsp; ) == [43,[ ; ],45 ] )
+test_ok(f.call(43,44) == [43,[44],45 ] )
+
+f = lambda { |b=42, *c, d| [b,c,d] }
+test_ok(f.call(&nbsp; &nbsp; &nbsp; 99) == [42,[ ; ],99] )
+test_ok(f.call(43&nbsp;  ,99) == [43,[ ; ],99] )
+test_ok(f.call(43,44,99) == [43,[44],99] )
+
+f = lambda { |b=42, &block| [b,block&amp;&block[]] }
+test_ok(f.call(&nbsp; ) &nbsp; &nbsp; == [42,nil] )
+test_ok(f.call(43)  ; &nbsp; == [43,nil] )
+test_ok(f.call(43)  ; &nbsp; == [43,nil] )
+test_ok(f.call(&nbsp; ) == [42,45 ] )
+test_ok(f.call(43) == [43,45 ] )
+test_ok(f.call(43) == [43,45 ] )
+
+f = lambda { |b=42, d| [b,d] }
+test_ok(f.call(&nbsp;  99) == [42,99] )
+test_ok(f.call(43,99) == [43,99] )
+test_ok(f.call(43,99) == [43,99] )
+
+
&nbsp;a,=*[1]
&nbsp;test_ok(a == 1)
 a,=*[[1]]
Index: parse.y
===================================================================
--- parse.y&nbsp;   (revision 16568)
+++ parse.y&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
 %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;   : f_arg ','; f_block_optarg ','; f_rest_arg opt_f_block_arg
&nbsp; &nbsp;  &nbsp;   &nbsp; &nbsp; {
 &nbsp;   &nbsp;   &nbsp; &nbsp; /*%%%*/
+&nbsp;   &nbsp;   &nbsp;   $$ = new_args($1, $3, $5, 0, $6);
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
+  ;  &nbsp;   &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;   &nbsp;   $$ = new_args($1, $3, $5, $7, $8);
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = params_new($1, $3, $5, $7, escape_Qundef($8));
+  ;  &nbsp;   &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;   &nbsp;   $$ = new_args($1, $3, 0, 0, $4);
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
+  ;  &nbsp;   &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;   &nbsp;   $$ = new_args($1, $3, 0, $5, $6);
+&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; &nbsp;   | f_arg ','; f_rest_arg opt_f_block_arg
+&nbsp;   &nbsp;   &nbsp; &nbsp; {
+ &nbsp;  &nbsp;   &nbsp; &nbsp; /*%%%*/
&nbsp; &nbsp;  &nbsp;   &nbsp;   $$ = new_args($1, 0, $3, 0, $4);
 ; &nbsp;  &nbsp;   &nbsp; &nbsp; /*%
   ;  &nbsp;   &nbsp;   $$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
-3202,6 +3235,38
 &nbsp;   &nbsp;   &nbsp;   $$ = params_new($1, Qnil,Qnil, Qnil, escape_Qundef($2));
&nbsp;    &nbsp;   &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;   &nbsp;   $$ = new_args(0, $1, $3, 0, $4);
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
+  ;  &nbsp;   &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;   &nbsp;   $$ = new_args(0, $1, $3, $5, $6);
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
+  ;  &nbsp;   &nbsp; &nbsp; %*/
;   &nbsp;   &nbsp; &nbsp; }
+ &nbsp;  &nbsp;   | f_block_optarg opt_f_block_arg
+&nbsp;   &nbsp;   &nbsp; &nbsp; {
+ &nbsp;  &nbsp;   &nbsp; &nbsp; /*%%%*/
+&nbsp;   &nbsp;   &nbsp;   $$ = new_args(0, $1, 0, 0, $2);
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
   &nbsp;   &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;   &nbsp;   $$ = new_args(0, $1, 0, $3, $4);
+&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; &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;   &nbsp;   &nbsp;   if (!is_local_id($1))
+&nbsp;   &nbsp;   &nbsp;   &nbsp; &nbsp; yyerror(&quot;formal argument must be local variable&quot;);
+&nbsp;   &nbsp;   &nbsp;   shadowing_lvar($1);
;   &nbsp;   &nbsp;   arg_var($1);
+ &nbsp;  &nbsp;   &nbsp;   $$ = NEW_OPT_ARG(0, assignable($1, $3));
+&nbsp;   &nbsp;   &nbsp; &nbsp; /*%
;   &nbsp;   &nbsp;   $$ = rb_assoc_new($1, $3);
+&nbsp;   &nbsp;   &nbsp; &nbsp; %*/
;   &nbsp;   &nbsp; &nbsp; }
+ &nbsp;  &nbsp;   ;
+
+f_block_optarg &nbsp;  : f_block_opt
+ &nbsp;  &nbsp;   &nbsp; &nbsp; {
;   &nbsp;   &nbsp; &nbsp; /*%%%*/
+&nbsp;   &nbsp;   &nbsp;   $$ = $1;
;   &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; /*%%%*/
+ &nbsp;  &nbsp;   &nbsp;   NODE *opts = $1;
+
+&nbsp;   &nbsp;   &nbsp;   while (opts->nd_next) {
+ &nbsp;  &nbsp;   &nbsp;   &nbsp; &nbsp; opts = opts->nd_next;
+&nbsp;   &nbsp;   &nbsp;   }
+&nbsp;   &nbsp;   &nbsp;   opts->nd_next = $3;
;   &nbsp;   &nbsp;   $$ = $1;
;   &nbsp;   &nbsp; &nbsp; /*%
+&nbsp;   &nbsp;   &nbsp;   $$ = rb_ary_push($1, $3);
+&nbsp;   &nbsp;   &nbsp; &nbsp; %*/
;   &nbsp;   &nbsp; &nbsp; }
+ &nbsp;  &nbsp;   ;
+
 f_optarg &nbsp;  : f_opt
&nbsp; &nbsp;  &nbsp;   &nbsp; &nbsp; {
 &nbsp;   &nbsp;   &nbsp; &nbsp; /*%%%*/
Re: block args w/ defaults (was Re: resolving lambda | ambiguity)
user name
2008-05-26 16:02:30
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've tried also with &block but the same results.

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'm very interested in this patch because AFAIR -> was
introduced to
handle arguments like methods (defaults, *args etc) and
maybe with
this patch it's unnecessary to have -> operator?

-- 
Radosław Bułat

http://radarek.jogger.pl
- mój blog
Re: block args w/ defaults (was Re: resolving lambda | ambiguity)
user name
2008-05-26 19:54:15
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.

Well, I guess just handling the syntax and putting it in the parse tree wasn't good enough.&nbsp; I only tested blocks on "lambda".&nbsp; All of these cases should print 2, but only "lambda" seems to work (the rest print 10):

def lam(&f);f;end
def yld(*a);yield(*a);end
p(lambda{|x=10|x}[2])
p(proc{|x=10|x}[2])
p(Proc.new{|x=10|x}[2])
p(lam{|x=10|x}[2])
p(yld(2){|x=10|x})

I9;ll see if I can fix these, but I don't know the code too well. ; Just reading and hacking it.  I think its stuff in proc.c that needs to change.&nbsp; I'll give it a shot, but matz is better suited.

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 didn't see this. ; Do you see this when you simply build the latest code and run the local ruby/irb:

./ruby -Ilib bin/irb

I haven't tried to install my local ruby. ; I just leave it in a local dir.

I'm very interested in this patch because AFAIR -> was introduced to
handle arguments like methods (defaults, *args etc) and maybe with
this patch it's unnecessary to have -> operator?

Exactly.

Re: block args w/ defaults (was Re: resolving lambda | ambiguity)
user name
2008-05-27 07:25:36
2008/5/27 Eric Mahurin <eric.mahuringmail.com>:
> 2008/5/26 Radosław Bułat <radek.bulatgmail.com>:
>> 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 didn't see this.  Do you see this when you simply
build the latest code
> and run the local ruby/irb:
>
> ./ruby -Ilib bin/irb

The same behavior. 2 seconds and my computer hangs.

> I haven't tried to install my local ruby.  I just leave
it in a local dir.
>
>> I'm very interested in this patch because AFAIR
-> was introduced to
>> handle arguments like methods (defaults, *args etc)
and maybe with
>> this patch it's unnecessary to have -> operator?
>
> Exactly.
>
>



-- 
Radosław Bułat

http://radarek.jogger.pl
- mój blog
[1-4]

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