首页 > 解决方案 > 可变参数究竟是如何工作的?

问题描述

我是 Swift 新手,在理解可变参数究竟是什么以及为什么它有用时遇到了一些麻烦。我目前正在关注在线 Swift 5.3 指南,这是为此类参数提供的示例。

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers

显然,被调用的可变参数numbers的类型为Double...,这允许它在函数体中作为常量数组使用。为什么函数返回Double(numbers.count)而不是 just numbers.count?而不是创建一个可变参数,为什么不直接创建一个参数来接收一个像这样的函数之外的数组呢?

func addition(numbers : [Int]) -> Int
{
    var total : Int = 0
    for number in numbers
    {
        total += number
    }
    return total
}

let totalBruhs : [Int] = [4, 5, 6, 7, 8, 69]
addition(numbers: totalBruhs)

另外,为什么每个函数只能有一个可变参数?

标签: swiftvariadic-functions

解决方案


可变参数需要(嗯,不需要,但很好)存在于 Swift 中,因为它们存在于 C 中,并且 Swift 中的许多东西都连接到 C。在 C 中,创建任意长度的快速数组并不像在 Swift 中那么简单。

如果您是从头开始构建 Swift 且不向后兼容 C,那么可能会添加它们,也可能不会。(虽然我打赌是的,只是因为很多 Swift 开发人员已经习惯了它们存在的语言。但话说回来,像 Zig 之类的语言有意摆脱了可变参数,所以我不知道。Zig 也证明了你不知道'不需要可变参数来桥接到 C,但仍然很好。@Rob 下面的评论值得一读。他可能没有错。另外,他的回答很有见地。

但它们也很方便,因为您不需要添加[...],这使得只有一个值时更好。特别是,考虑类似print

func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

如果没有可变参数,您需要[...]输入每个print调用,或者您需要重载。Variadic 并没有改变这里的世界,但它有点好。当您考虑过载会产生的歧义时,这特别好。假设您没有可变参数,而是有两个重载:

func print(_ items: [Any]) { ... }
func print(_ item: Any) { print([item]) }

这实际上有点模棱两可,因为 Array 也是 Any 的一种。所以print([1,2,3])会打印[[1,2,3]]。我确信有一些可能的解决方法,但可变参数可以很好地解决这个问题。

只能有一个,否则会出现模棱两可的情况。

func f(_ xs: Int..., _ ys: Int...)

在这种情况下应该f(1,2,3)怎么做?什么是xs和什么是ys

您在此处显示的功能不会返回Double(numbers.count)。它转换numbers.count为 Double,因此可以分为另一个 Double。函数返回total / Double(numbers.count)


推荐阅读