1

以下代码:

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 已经过测试。

4

3 回答 3

3

I'm currently using Ruby 2.1.0p0.

The "problem" can be simplified a little with the following example:

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

Here, the method foo has one OPTIONAL argument arg1 (with default {}) and one OPTIONAL keyword argument, arg2.

If you call:

foo({key1: 'value1'})

You get the error:

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

The reason is that Ruby is attempting to match the only argument you gave (with keyword key1) to the only OPTIONAL keyword argument which is keyword arg2. They don't match, thus the error.

In the next example:

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

We get the result:

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

This makes sense because I provided two arguments. Ruby can match arg2: 1 to the second keyword argument and accepts {val1: 'value', val2: 'value2'} as a substitute for the first optional argument.

I do not consider the behaviors above a bug.

于 2014-08-19T18:31:28.940 回答
2

Obviously, parameters resolution works the other way around from what you expected. In addition to konsolebox' answer, you can fix it by calling the constructor with an additional empty hash:

Test.new({key1: 'value1'}, {})
于 2014-08-19T18:26:19.217 回答
-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"]
于 2014-08-19T18:22:45.980 回答