Issue #11967 has been reported by Markus Doits.

----------------------------------------
Bug #11967: Mixing kwargs with optional parameters change way method parameters are parsed
https://bugs.ruby-lang.org/issues/11967

* Author: Markus Doits
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
I have the following method:

    def test(first_param = nil, keyword_arg: nil)
      puts "first_param: #{first_param}"
      puts "keyword_arg: #{keyword_arg}"
    end

All the following calls do what I expect them to do:

    test(:something)
    #=> first_param: something
    #   keyword_arg:
    
    test(nil, keyword_arg: :keyword_arg)
    #=> first_param:
    #   keyword_arg: keyword_arg
    
    test({ first_param: :is_a_hash }, keyword_arg: :is_still_working)
    #=> first_param: {:first_param=>:is_a_hash}
    #   keyword_arg: is_still_working

But omitting the optional `keyword_arg` and passing a hash as first argument gives me an error:

    test(first_param: :is_a_hash)
    #=> test.rb:1:in `test': unknown keyword: first_param (ArgumentError)
    #           from test.rb:12:in `<main>'

I'd expect it to set `first_param` to `{ first_param: :is_hash }` and `keyword_arg` being `nil`.

It seems it is interpreting every hash as keyword arg:

    test(keyword_arg: :should_be_first_param)
    #=> first_param:
    #   keyword_arg: should_be_first_param

This should have set `first_param` to `{ keyword_arg: :should_be_first_param }`, leaving `keyword_arg` `nil` in my opinion.

Making the first parameter *mandatory* and everything works like I'd expect to:

    def test(first_param, keyword_arg: nil)
      puts "first_param: #{first_param}"
      puts "keyword_arg: #{keyword_arg}"
    end

    test(first_param: :is_a_hash)
    #=> first_param: {:first_param=>:is_a_hash}
    #   keyword_arg:

    test(keyword_arg: :should_be_first_param)
    #=> first_param: {:keyword_arg=>:should_be_first_param}
    #=> keyword_arg:

I'd expect making a parameter optional does not change the way parameters are parsed.

Is this a parser oddity or expected behaviour?



-- 
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>