关键字参数中的Ruby奇怪行为与位置混合

时间:2014-08-19 18:09:54

标签: ruby ruby-2.1 keyword-argument

以下代码:

class Test
  attr_reader :args
  def initialize(arg1={}, arg2: 'value2')
    @args = [arg1, arg2]
  end
end
t = Test.new({key1: 'value1'})
puts t.args

我预计会打印出内容为[{key1: 'value1'}, 'value2']的数组 但我得到了:

test.rb:11:in `new': unknown keywords: val1, val2 (ArgumentError)
    from test.rb:11:in `<main>'

更奇怪的是,使用{val1: 'value', val2: 'value2'}, arg2: 1)调用相同的测试类作为参数我得到输出:{:val1=>"value", :val2=>"value2"}

这种行为的来源在哪里,我错过了什么或者它是一个错误? Ruby版本2.1.1和2.1.2已经过测试。

3 个答案:

答案 0 :(得分:3)

我目前正在使用Ruby 2.1.0p0。

使用以下示例可以简化“问题”:

def foo(arg1 = {}, arg2: 'value1')
  [arg1, arg2]
end

此处,方法foo有一个OPTIONAL参数arg1(默认为{})和一个OPTIONAL关键字参数arg2

如果你打电话:

foo({key1: 'value1'})

您收到错误:

ArgumentError: unknown keyword: key1
        from (irb):17
        from /home/mark/.rvm/rubies/ruby-2.1.0/bin/irb:11:in `<main>'

原因是Ruby试图将您给出的唯一参数(使用关键字key1)与唯一的OPTIONAL关键字参数(关键字arg2)相匹配。它们不匹配,因此错误。

在下一个例子中:

foo({val1: 'value', val2: 'value2'}, arg2: 1)

我们得到了结果:

=> [{:val1=>"value", :val2=>"value2"}, 1]

这是有道理的,因为我提供了两个论点。 Ruby可以将arg2: 1与第二个关键字参数匹配,并接受{val1: 'value', val2: 'value2'}作为第一个可选参数的替代。

我不认为上面的行为是错误的。

答案 1 :(得分:2)

显然,参数分辨率与您的预期相反。除了konsolebox&#39;回答,您可以通过使用额外的空哈希调用构造函数来修复它:

Test.new({key1: 'value1'}, {})

答案 2 :(得分:-1)

请这样做:

class Test
  attr_reader :args
  def initialize(arg1={}, arg2 = 'value2')  ## Changed : to =.
    @args = [arg1, arg2]
  end
end
t = Test.new({key1: 'value1'})
puts t.args.inspect

输出:

[{:key1=>"value1"}, "value2"]