在方法调用中使用Ruby的double-splat('**')有什么意义?

qc6wkl3g  于 2023-01-08  发布在  Ruby
关注(0)|答案(1)|浏览(91)

通过一个splat,我们可以将一个数组扩展为多个参数,这与直接传递数组有很大的不同:

def foo(a, b = nil, c = nil)
  a
end

args = [1, 2, 3]

foo(args)  # Evaluates to foo([1, 2, 3]) => [1, 2, 3]
foo(*args) # Evaluates to foo(1, 2, 3)   => 1

然而,对于关键字参数,我看不出有什么区别,因为它们只是哈希的语法糖:

def foo(key:)
  key
end

args = { key: 'value' }

foo(args)   # Evaluates to foo(key: 'value') => 'value'
foo(**args) # Evaluates to foo(key: 'value') => 'value'

除了良好的对称性之外,在方法调用中使用双splats还有什么实际的原因吗?(注意,这与在方法定义中使用双splats是不同的)

lf5gs5x2

lf5gs5x21#

使用单个参数的示例是退化情况。
看看一个重要的例子,您可以很快看到使用新的**运算符的好处:

def foo (args)
  return args
end

h1 = { b: 2 }
h2 = { c: 3 }

foo(a: 1, **h1)       # => {:a=>1, :b=>2}
foo(a: 1, **h1, **h2) # => {:a=>1, :b=>2, :c=>3}
foo(a: 1, h1)         # Syntax Error: syntax error, unexpected ')', expecting =>
foo(h1, h2)           # ArgumentError: wrong number of arguments (2 for 1)

使用**运算符允许我们在调用点合并现有的散列(沿着单独的键-值参数),而不是添加另一行(或更多行)代码将所有值组合成一个散列,然后将其作为参数传递。
(历史上的一个小问题--在Ruby 2.1.1中,有一个错误,散列would be destructively modified出现了,尽管后来已经打了补丁。)

相关问题