Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112016-01-07T14:25:06ZRuby Issue Tracking System
Redmine Ruby master - Bug #11967 (Rejected): Mixing kwargs with optional parameters changes way method pa...https://bugs.ruby-lang.org/issues/119672016-01-07T14:25:06Zmarkus_d (Markus Doits)
<p>I have the following method:</p>
<pre><code>def test(first_param = nil, keyword_arg: nil)
puts "first_param: #{first_param}"
puts "keyword_arg: #{keyword_arg}"
end
</code></pre>
<p>All the following calls do what I expect them to do:</p>
<pre><code>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
</code></pre>
<p>But omitting the optional <code>keyword_arg</code> and passing a hash as first argument gives me an error:</p>
<pre><code>test(first_param: :is_a_hash)
#=> test.rb:1:in `test': unknown keyword: first_param (ArgumentError)
# from test.rb:12:in `<main>'
</code></pre>
<p>I'd expect it to set <code>first_param</code> to <code>{ first_param: :is_hash }</code> and <code>keyword_arg</code> being <code>nil</code>.</p>
<p>It seems it is interpreting every hash as keyword arg:</p>
<pre><code>test(keyword_arg: :should_be_first_param)
#=> first_param:
# keyword_arg: should_be_first_param
</code></pre>
<p>This should have set <code>first_param</code> to <code>{ keyword_arg: :should_be_first_param }</code>, leaving <code>keyword_arg</code> <code>nil</code> in my opinion.</p>
<p>Making the first parameter <em>mandatory</em> and everything works like I'd expect to:</p>
<pre><code>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:
</code></pre>
<p>I'd expect making a parameter optional does not change the way parameters are parsed.</p>
<p>Is this a parser oddity or expected behaviour?</p>