double *(splat)运算符有什么作用


214

您是否看到过这样声明的函数?

def foo a, **b
  ...
end

我知道单身*是splat运算符。什么**意思

Answers:


373

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}]

44
这可以完美地回答这个问题,但是我有一个小的附录。正如可以在传递的数组上使用splat运算符一样,可以在散列上使用double splat。如果opts = {d: 40, e: 50}foo 10, opts, f: 60则将分配{f: 60}c,而foo 10, **opts, f: 60将分配{d: 40, e: 50, f: 60}。为了获得第二个效果,以前您必须merge显式创建数组。
brymck

我认为这对于设置方法的可选哈希参数很有用
bigpotato 2013年

可能值得一提的是,如果将关键字参数与关键字splat混合使用,则关键字splat必须排在关键字参数之后。
MrMesees

43

这是从Ruby 2.0开始可用的double splat运算符。

它捕获所有关键字参数(也可以是一个简单的哈希,这是在关键字参数成为Ruby语言的一部分之前模拟关键字参数的惯用方式)

def my_method(**options)
  puts options.inspect
end

my_method(key: "value")

上面的代码将打印{key:value}到控制台。

就像单个splat运算符捕获所有常规参数一样,但是您得到的不是hash而是数组

现实生活中的例子:

例如在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,代码获得了很多简洁。


20

另外,您可以在呼叫方使用它,如下所示:

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}

5
哇,double-splat与ES6的对象传播运算符类似。
mpoisot

1
谢谢,这是我一直在寻找的确认信息。
Qortex
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.