Project

General

Profile

Bug #14130

Keyword arguments are ripped from the middle of hash if argument have default value

Added by zverok (Victor Shepelev) over 1 year ago. Updated 11 months ago.

Status:
Open
Priority:
Normal
Target version:
-
[ruby-core:83881]

Description

Here is the code:

def test1(source = {}, **opts)
  puts "SOURCE: #{source}, OPTS: #{opts}"
end

def test2(source, **opts)
  puts "SOURCE: #{source}, OPTS: #{opts}"
end

puts "No source"
test1(length: 2000) 
# 1. SOURCE: {}, OPTS: {:length=>2000} -- OK, it is reasonable.
test2(length: 2000) 
# 2. SOURCE: {:length=>2000}, OPTS: {} -- Exactly as expected.

puts
puts "Source is mixed hash"
test1('River name' => 'Mississippi', length: 2000, 'Country' => 'USA')
# 3. SOURCE: {"River name"=>"Mississippi", "Country"=>"USA"}, OPTS: {:length=>2000} -- It is already a bit weird
test2('River name' => 'Mississippi', length: 2000, 'Country' => 'USA')
# 4. SOURCE: {"River name"=>"Mississippi", :length=>2000, "Country"=>"USA"}, OPTS: {} -- The most weird thing!

My concern is cases (3) and (4). Ripping keyword argument from what from any logic looks like a middle of a hash (3) is already pretty strange. But the fact that this behavior depends on whether first argument has or has not default value (3 vs 4) clearly looks like some bug?

Checked on several recent versions, including ruby 2.5.0dev (2017-09-11 trunk 59836) [x86_64-linux] (the last that is available on my RVM), behavior is consistent between them.


Related issues

Related to Ruby master - Feature #14183: "Real" keyword argumentOpenActions

History

#1

Updated by hsbt (Hiroshi SHIBATA) over 1 year ago

Updated by marcandre (Marc-Andre Lafortune) 11 months ago

  • Assignee set to nobu (Nobuyoshi Nakada)

This is a bug.

test1('River name' => 'Mississippi', length: 2000, 'Country' => 'USA')
# 3. SOURCE: {"River name"=>"Mississippi", "Country"=>"USA"}, OPTS: {:length=>2000} -- It is already a bit weird

My understanding is that under no circumstance should a mixed hash be split in two like this.

Ruby should recognize that some keys are no symbols and thus this hash can't be a keyword parameter hash and must be a positional argument. The correct result should thus be:

SOURCE: {"River name"=>"Mississippi", :length=>2000, "Country"=>"USA"}, OPTS: {}

Note that this should still be true even if the :length key was the last one.

To obtain the current result, one would have to call test1({'River name' => 'Mississippi', 'Country' => 'USA'}, length: 2000)

Also available in: Atom PDF