在方法调用中使用 Ruby 的双星号(`**`)有什么作用?

9

使用单个星号(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'

除了美观的对称性外,使用双星号在方法调用中还有其他实际的原因吗?(请注意,这与在方法定义中使用它们是不同的)

3
关于 Ruby 方法定义中的双星号 ** 的类似问题,有一个相关信息。接受答案的评论稍微涉及到使用 ** 对参数的影响。 - Daniël Knippers
你应该提取那个评论并将其放在这里,完美地回答了这个问题。 - Mike H-R
@DaniëlKnippers 好的,请这样做 :) - Renato Zannon
我现在正在使用手机,如果有其他人或您自己发布答案也可以。 :-) - Daniël Knippers
1个回答

9

只传入一个参数的示例是退化情况。

看一个非平凡的情况,你可以很快地看到拥有新的**运算符的优势:

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中,有一个bug,使得扩展的哈希表会被破坏性地修改,但这个问题已经被修复。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接