双 * (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
。为了实现第二个效果,以前您需要明确地merge
d 数组。
我认为这对于设置方法的可选哈希参数很有用
可能值得注意的是,如果将关键字参数与关键字 splat 混合,则关键字 splat 需要在关键字参数之后。以上是关于双 * (splat) 运算符有啥作用的主要内容,如果未能解决你的问题,请参考以下文章
Matlab 中是不是有 splat 运算符(或等效运算符)?
Haskell 有像 Python 和 Ruby 这样的 splat 运算符吗?