你见过像这样声明的函数吗?
def foo a, **b
...
end
我知道单个*
是splat运算符。 **
是什么意思?
答案 0 :(得分:334)
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}]
答案 1 :(得分:39)
这是自以来可用的双splat 运算符。
它捕获所有关键字参数(也可以是一个简单的哈希,这是在它们成为Ruby语言的一部分之前模拟关键字参数的惯用方法)
def my_method(**options)
puts options.inspect
end
my_method(key: "value")
以上代码将{key:value}
打印到控制台。
就像单个splat运算符捕获所有常规参数一样,但不是数组,而是获得哈希。
现实生活中的例子:
例如在Rails中,cycle
方法如下所示:
def cycle(first_value, *values)
options = values.extract_options!
# ...
end
可以像这样调用此方法:cycle("red", "green", "blue", name: "colors")
。
这是一个非常常见的模式:你接受一个参数列表,最后一个是一个选项哈希,例如,可以使用ActiveSupport的extract_options!
提取。
在Ruby 2.0中,您可以简化这些方法:
def cycle(first_value, *values, **options)
# Same code as above without further changes!
end
不可否认,如果您已经在使用ActiveSupport,那只是一个小小的改进,但对于普通的Ruby,代码可以获得相当多的简洁。
答案 2 :(得分:11)
此外,您可以在呼叫方这样使用它:
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}