From: Marc-Andre Lafortune Date: 2013-03-19T03:19:24+09:00 Subject: [ruby-core:53511] Re: [ruby-trunk - Bug #8040] Unexpect behavior when using keyword arguments --047d7b6d7bae77587104d836f2d5 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Matz: could you please confirm that mandatory arguments should be fulfilled before checking for hash argument to fulfill named parameters? BTW, also asked on StackOverflow today: http://stackoverflow.com/questions/15480236/how-can-i-prevent-a-positional-= argument-from-being-expanded-into-keyword-argumen On Sun, Mar 17, 2013 at 10:36 PM, pabloh (Pablo Herrero) < pablodherrero@gmail.com> wrote: > > Issue #8040 has been updated by pabloh (Pablo Herrero). > > > I also like Yusuke's approach. Is it been considered? > > ---------------------------------------- > Bug #8040: Unexpect behavior when using keyword arguments > https://bugs.ruby-lang.org/issues/8040#change-37685 > > Author: pabloh (Pablo Herrero) > Status: Assigned > Priority: Normal > Assignee: matz (Yukihiro Matsumoto) > Category: > Target version: > ruby -v: 2.0.0-p0 > > > =3Dbegin > There is an odd behavior when calling methods with the new keyword > arguments syntax, when you have a method defined with mandatory arguments > that also takes options, like this: > > def foo value, **keywords > puts [value,keywords].inspect > end > > foo("somthing") #This works > foo("somthing", key: 'value') #This also works > > foo(Hash.new(something: 'else')) #This raises 'ArgumentError: wrong > number of arguments (0 for 1)' > > This feels weird regardless the fact that keyword arguments are a Hash at > the bottom, since you ARE PASSING an argument. > > Other side effect from this, is that when you call the method ((|foo|)) > with a single argument, you can't anticipate how many argument you will b= e > actually passing at runtime unless you know beforehand the argument's cla= ss. > > What's maybe even more concerning is the fact than this happens even when > you pass an argument which class derives from Hash: > > class MyDirectory < Hash; end > > foo(MyDirectory.new(something: 'else')) #This also raises > 'ArgumentError: wrong number of arguments (0 for 1)' > > > Besides finding this behavior surprising, I think this could also possibl= y > lead to old code been unexpectedly broken when updating old methods that > takes options to the new syntax. > > For example if you have this code: > > def foo_with_options argument, options =3D {} > #Do some stuff with options > end > > > #And at someplace else... > > my_hash_thingy =3D Hash.new > foo_with_options(my_hash_thingy) #Only passing mandatory argument, with > no options, works fine. > > > When updating to the new syntax: > > def foo_with_options argument, an_option: 'value1', another_option: > 'value2' > #Do some stuff with options > end > > > > #And at someplace else... > > my_hash_thingy =3D Hash.new > foo_with_options(my_hash_thingy) #Only passing mandatory argument, with > no options, doesn't work anymore. > =3Dend > > > -- > http://bugs.ruby-lang.org/ > > --047d7b6d7bae77587104d836f2d5 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Matz: could you please confirm that mandatory argumen= ts should be fulfilled before checking for hash argument to fulfill named p= arameters?

BTW, also asked on StackOverflow today:=

http://stackoverflow.com/questions/15480236/how-can-i-p= revent-a-positional-argument-from-being-expanded-into-keyword-argumen


On Sun,= Mar 17, 2013 at 10:36 PM, pabloh (Pablo Herrero) <pablodherrero@gma= il.com> wrote:

Issue #8040 has been updated by pabloh (Pablo Herrero).


I also like Yusuke's approach. Is it been considered?

----------------------------------------
Bug #8040: Unexpect behavior when using keyword arguments
https://bugs.ruby-lang.org/issues/8040#change-37685

Author: pabloh (Pablo Herrero)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:
ruby -v: 2.0.0-p0


=3Dbegin
There is an odd behavior when calling methods with the new keyword argument= s syntax, when you have a method defined with mandatory arguments that also= takes options, like this:

=A0 def foo value, **keywords
=A0 =A0 puts [value,keywords].inspect
=A0 end

=A0 foo("somthing") #This works
=A0 foo("somthing", key: 'value') #This also works

=A0 foo(Hash.new(something: 'else')) #This raises 'ArgumentErro= r: wrong number of arguments (0 for 1)'

This feels weird regardless the fact that keyword arguments are a Hash at t= he bottom, since you ARE PASSING an argument.

Other side effect from this, is that when you call the method ((|foo|)) wit= h a single argument, you can't anticipate how many argument you will be= actually passing at runtime unless you know beforehand the argument's = class.

What's maybe even more concerning is the fact than this happens even wh= en you pass an argument which class derives from Hash:

=A0 class MyDirectory < Hash; end

=A0 foo(MyDirectory.new(something: 'else')) #This also raises '= ArgumentError: wrong number of arguments (0 for 1)'


Besides finding this behavior surprising, I think this could also possibly = lead to old code been unexpectedly broken when updating old methods that ta= kes options to the new syntax.

For example if you have this code:

=A0 def foo_with_options argument, options =3D {}
=A0 =A0 #Do some stuff with options
=A0 end


=A0 #And at someplace else...

=A0 my_hash_thingy =3D Hash.new
=A0 foo_with_options(my_hash_thingy) #Only passing mandatory argument, with= no options, works fine.


When updating to the new syntax:

=A0 def foo_with_options argument, an_option: 'value1', another_opt= ion: 'value2'
=A0 =A0 #Do some stuff with options
=A0 end



=A0 #And at someplace else...

=A0 my_hash_thingy =3D Hash.new
=A0 foo_with_options(my_hash_thingy) #Only passing mandatory argument, with= no options, doesn't work anymore.
=3Dend


--
http://bugs.ruby-l= ang.org/


--047d7b6d7bae77587104d836f2d5--