双 * (splat) 运算符有啥作用

Posted

技术标签:

【中文标题】双 * (splat) 运算符有啥作用【英文标题】:What does a double * (splat) operator do双 * (splat) 运算符有什么作用 【发布时间】:2013-08-19 19:04:43 【问题描述】:

你见过这样声明的函数吗?

def foo a, **b
  ...
end

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

【问题讨论】:

【参考方案1】:

此外,您可以像这样在调用方使用它:

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

【讨论】:

哇,double-splat 类似于 ES6 的对象扩展运算符。 谢谢,这就是我要找的确认信息。【参考方案2】:

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

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

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

my_method(key: "value")

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

就像单个 splat 运算符捕获所有常规参数一样,但您得到的不是 array,而是 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,代码获得了相当多的简洁性。

【讨论】:

【参考方案3】:

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]

【讨论】:

这完美地回答了这个问题,但我有一个小附录。就像 splat 运算符可以用于您传递的数组一样,双 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。为了实现第二个效果,以前您需要明确地merged 数组。 我认为这对于设置方法的可选哈希参数很有用 可能值得注意的是,如果将关键字参数与关键字 splat 混合,则关键字 splat 需要在关键字参数之后。

以上是关于双 * (splat) 运算符有啥作用的主要内容,如果未能解决你的问题,请参考以下文章

Matlab 中是不是有 splat 运算符(或等效运算符)?

Haskell 有像 Python 和 Ruby 这样的 splat 运算符吗?

如何将数组传递给接受带有 splat 运算符的属性的方法?

Double-splat 运算符破坏性地修改了哈希——这是一个 Ruby 错误吗?

Ruby,Splat 的源代码?

^= 运算符有啥作用?