Issue #8316 has been updated by Andrew Schwartz.

ruby -v changed from ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux] to ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin13]

This is unfortunately still an issue with default values in positional arguments:

2.2.2 > def foo(hash={}, opt: true); p hash; p opt; end
 => :foo
2.2.2 > foo({a: 1})
ArgumentError: unknown keyword: a

Expected behavior is that foo can be called with a hash argument in the first position without needing to specify the optional keyword args.


Yusuke Endoh wrote:
> This issue was solved with changeset r40992.
> Pablo, thank you for reporting this issue.
> Your contribution to Ruby is greatly appreciated.
> May Ruby be with you.
> 
> 
> ----------
> * vm_insnhelper.c (vm_callee_setup_keyword_arg,
>   vm_callee_setup_arg_complex): consider a hash argument for keyword
>   only when the number of arguments is more than the expected
>   mandatory parameters.  [ruby-core:53199] [ruby-trunk - Bug #8040]
> 
> * test/ruby/test_keyword.rb: update a test for above.



----------------------------------------
Bug #8316: Can't pass hash to first positional argument; hash interpreted as keyword arguments
https://bugs.ruby-lang.org/issues/8316#change-55988

* Author: Tyler Rick
* Status: Closed
* Priority: Normal
* Assignee: Yusuke Endoh
* ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin13]
* Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN
----------------------------------------
I'm able to pass any other type of object to my first argument:

 def foo(hash, opt: true)
   puts "hash: #{hash}, opt: #{opt.inspect}"
 end
 
 foo 'a'                 # => hash: a, opt: true
 foo [{a:1}]             # => hash: [{:a=>1}], opt: true
 foo [{a:1}], opt: false # => hash: [{:a=>1}], opt: false

But when I try to pass a hash, it raises an ArgumentError:

 foo({a:1})  # Raises ArgumentError: unknown keyword: a
 # Expected behavior: hash: {:a=>1}, opt: true

I tried to work around the "unknown keyword" error by using ** but ended up getting a "wrong number of arguments (0 for 1)" error instead.

 def foo_with_extra(hash, **extra)
   puts "hash: #{hash}, extra: #{extra.inspect}"
 end
 
 foo_with_extra 'a'                 # hash: a, extra: {}
 foo_with_extra [{a:1}]             # hash: [{:a=>1}], extra: {}
 foo_with_extra [{a:1}], opt: false # hash: [{:a=>1}], extra: {:opt=>false}
 
 foo_with_extra({a:1})  # Raises ArgumentError: wrong number of arguments (0 for 1)
 # Expected behavior: hash: {:a=>1}, extra: {}

This behavior is surprising and I haven't seen it mentioned anywhere before. Is it really intentional?



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>