如何将哈希项映射到方法参数?

Fil*_*vić 4 ruby method-invocation

我有一个带有冗长可选参数列表的方法,例如:

def foo(foo = nil, bar = nil, baz = nil, qux = nil)
    # no-op
end
Run Code Online (Sandbox Code Playgroud)

我认为调用方法并将分割散列作为参数传递会通过将键与方法参数匹配来将散列项映射到参数:

params = { bar: 'bar', foo: 'foo' }
foo(*params)
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我在使用拆分哈希调用方法后检查局部变量时,如果我传入一个split数组,我会得到我所期望的,但这不是我希望的:

foo == [:bar, 'bar'] # hoped: foo == 'foo'
bar == [:foo, 'foo'] # hoped: bar == 'bar'
Run Code Online (Sandbox Code Playgroud)

我在这里缺少什么?

Nik*_* B. 8

(这个答案指的是当问题被问到时最新的Ruby版本.请参阅编辑今天的情况.)

Ruby不支持按名称传递参数.图示运营商(*)调用扩展任意枚举to_ary它并拼接结果到参数列表.在您的情况下,您传入的可枚举是一个哈希,它被转换为一个键值对数组:

[2] pry(main)> params.to_a
=> [[:bar, "bar"], [:foo, "foo"]]
Run Code Online (Sandbox Code Playgroud)

所以函数的前两个参数将是值[:bar, "bar"][:foo, "foo"](不管它们的参数名称!).

如果你想在Ruby中使用类似于关键字参数的东西,你可以利用在将哈希作为最后一个参数传递给函数时不需要大括号的事实:

def foo(opts = {})
    bar = opts[:bar] || <default>
    foo = opts[:foo] || <default>
    # or with a lot of parameters:
    opts = { :bar => <default>, :foo => <default>, ... }.merge(opts)
end

foo(foo: 3)  # equivalent to foo({ foo: 3 })
Run Code Online (Sandbox Code Playgroud)

编辑:

从版本2.0开始,Ruby现在支持使用专用语法的命名参数.感谢用户jgoyon指出了这一点.