你见过这样声明的函数吗?
def foo a, **b ... end
我理解单个*是splat操作符。**是什么意思?
*
**
Ruby 2.0引入了关键字参数,而**与*类似,只是用于关键字参数。它返回一个带有键/值对的散列。
对于这段代码:
def foo(a, *b, **c) [a, b, c] end
下面是一个演示:
> foo 10 => [10, [], {}] > foo 10, 20, 30 => [10, [20, 30], {}] > foo 10, 20, 30, d: 40, e: 50 => [10, [20, 30], {:d=>40, :e=>50}] > foo 10, d: 40, e: 50 => [10, [], {:d=>40, :e=>50}]
这是自Ruby 2.0以来可用的双长条木板操作符。
它捕获所有关键字参数(也可以是一个简单的散列,这是在关键字参数成为Ruby语言的一部分之前模拟关键字参数的惯用方法)
def my_method(**options) puts options.inspect end my_method(key: "value")
上面的代码将{key:value}打印到控制台。
{key:value}
就像单个splat操作符捕获所有常规参数一样,但不是数组,而是哈希。
现实生活中的例子:
例如,在Rails中cycle方法看起来像这样:
cycle
def cycle(first_value, *values) options = values.extract_options! # ... end
这个方法可以像这样调用:cycle("red", "green", "blue", name: "colors")。
cycle("red", "green", "blue", name: "colors")
这是一个非常常见的模式:你接受一个参数列表,最后一个是一个选项哈希,可以提取-例如-使用ActiveSupport的extract_options!。
extract_options!
在Ruby 2.0中,你可以简化这些方法:
def cycle(first_value, *values, **options) # Same code as above without further changes! end
诚然,如果您已经在使用ActiveSupport,这只是一个小的改进,但对于纯Ruby,代码获得了相当多的简练。
此外,你可以像这样在调用方使用它:
def foo(opts); p opts end bar = {a:1, b:2} foo(bar, c: 3) => ArgumentError: wrong number of arguments (given 2, expected 1) foo(**bar, c: 3) => {:a=>1, :b=>2, :c=>3}
就你的情况而言,以上答案是准确的。
然而,双splat运算符也可以在Ruby语言中用于算术运算。例如,x^y可以写成x**y。
x^y
x**y
更多信息请参考stackover问题。