Ruby 具有可选的第一个散列参数和关键字参数的奇数方法行为
我有以下方法:Ruby 具有可选的第一个散列参数和关键字参数的奇数方法行为,ruby,hash,optional-parameters,keyword-argument,Ruby,Hash,Optional Parameters,Keyword Argument,我有以下方法: def test(first_param = nil, keyword_arg: nil) puts "first_param: #{first_param}" puts "keyword_arg: #{keyword_arg}" end 以下所有调用都会执行我希望他们执行的操作: test(:something) #=> first_param: something # keyword_arg: test(nil, keyword_arg: :keywor
def test(first_param = nil, keyword_arg: nil)
puts "first_param: #{first_param}"
puts "keyword_arg: #{keyword_arg}"
end
以下所有调用都会执行我希望他们执行的操作:
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
但是省略可选的关键字_arg
并将哈希作为第一个参数传递给我会出现错误:
test(first_param: :is_a_hash)
#=> test.rb:1:in `test': unknown keyword: first_param (ArgumentError)
# from test.rb:12:in `<main>'
这应该将first_param
设置为{keyword_arg::should_be_first_param}
,在我看来,留下keyword_arg
为零
这是解析器错误还是预期行为?在ruby 2.3.0和2.2.4上测试
编辑:将第一个参数设置为强制参数,所有操作都与我期望的一样:
def test_mandatory(first_param, keyword_arg: nil)
puts "first_param: #{first_param}"
puts "keyword_arg: #{keyword_arg}"
end
test_mandatory(first_param: :is_a_hash)
#=> first_param: {:first_param=>:is_a_hash}
# keyword_arg:
test_mandatory(keyword_arg: :should_be_first_param)
#=> first_param: {:keyword_arg=>:should_be_first_param}
# keyword_arg:
我希望使参数成为可选参数不会改变参数的解析方式
我打开了一个,然后开发人员可以弄清楚它是打算这样做,还是kword args的副作用。这是根据: 这种行为可能令人惊讶,但却是故意的 它归结为首先优先填充关键字参数 而不是填充未命名的参数。它实际上是唯一的 可能的方式。除其他事项外,请考虑以下事项 例如:
def foo(*rest, bar: 42)
end
如果我们不首先对命名的参数进行优先级排序,那么就没有了
在本例中,指定条形图值的方法
所以Ruby检查:
- 在填充所有必需的未命名参数之后
- 如果剩下的最后一个参数是类似散列的
- 所有的钥匙都是符号
- 调用的方法使用关键字参数
def foo(a = nil, b: nil)
p a, b
end
foo(:b => 42) # => nil, 42
foo('b' => 42) # => {"b" => 42}, nil
“这应该将
first_-param
设置为{keyword_-arg::should_-be_-first_-param}
,让关键字_-arg
在我看来为零。”--为什么?你不认为它是不明确的吗?我只给这个方法一个参数。当它不是散列时,它设置第一个参数(测试(:某物)
)。但是,如果参数是散列,它不会设置first_param
,而是将散列解释为关键字参数。为什么行为取决于参数的类型?这是不合逻辑的(至少对我来说)。
def foo(a = nil, b: nil)
p a, b
end
foo(:b => 42) # => nil, 42
foo('b' => 42) # => {"b" => 42}, nil