跳至内容

展开参数和元组

方法可以使用展开参数(*)接收可变数量的参数,展开参数只能出现一次,并且可以在任何位置

def sum(*elements)
  total = 0
  elements.each do |value|
    total += value
  end
  total
end

sum 1, 2, 3      # => 6
sum 1, 2, 3, 4.5 # => 10.5

传递的参数将在方法体中变为一个 元组

# elements is Tuple(Int32, Int32, Int32)
sum 1, 2, 3

# elements is Tuple(Int32, Int32, Int32, Float64)
sum 1, 2, 3, 4.5

展开参数后面的参数只能以命名参数的形式传递

def sum(*elements, initial = 0)
  total = initial
  elements.each do |value|
    total += value
  end
  total
end

sum 1, 2, 3              # => 6
sum 1, 2, 3, initial: 10 # => 16

展开参数后面的没有默认值的 parameter 是必须的命名参数

def sum(*elements, initial)
  total = initial
  elements.each do |value|
    total += value
  end
  total
end

sum 1, 2, 3              # Error, missing argument: initial
sum 1, 2, 3, initial: 10 # => 16

具有不同必须的命名参数的两个方法会相互重载

def foo(*elements, x)
  1
end

def foo(*elements, y)
  2
end

foo x: "something" # => 1
foo y: "something" # => 2

展开参数也可以不命名,含义是“在此之后,命名参数随之而来”

def foo(x, y, *, z)
end

foo 1, 2, 3    # Error, wrong number of arguments (given 3, expected 2)
foo 1, 2       # Error, missing argument: z
foo 1, 2, z: 3 # OK

展开元组

元组可以通过使用 * 展开到方法调用中

def foo(x, y)
  x + y
end

tuple = {1, 2}
foo *tuple # => 3

双展开参数和命名元组

双展开参数(**)会捕获没有与其他参数匹配的命名参数。该参数的类型是 NamedTuple

def foo(x, **other)
  # Return the captured named arguments as a NamedTuple
  other
end

foo 1, y: 2, z: 3    # => {y: 2, z: 3}
foo y: 2, x: 1, z: 3 # => {y: 2, z: 3}

双展开命名元组

NamedTuple 可以通过使用 ** 展开到方法调用中

def foo(x, y)
  x - y
end

tuple = {y: 3, x: 10}
foo **tuple # => 7