【问题标题】:How to forward functions with variadic parameters?如何转发具有可变参数的函数?
【发布时间】:2014-07-25 14:48:52
【问题描述】:

在 Swift 中,如何将 Array 转换为 Tuple?

问题出现是因为我试图在一个接受可变数量参数的函数内部调用一个接受可变数量参数的函数。

// Function 1
func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
// Example Usage
sumOf(2, 5, 1)

// Function 2
func averageOf(numbers: Int...) -> Int {
    return sumOf(numbers) / numbers.count
}

这个averageOf 实现对我来说似乎是合理的,但它无法编译。当您尝试调用sumOf(numbers) 时会出现以下错误:

Could not find an overload for '__converstion' that accepts the supplied arguments

averageOf 内部,numbers 的类型为Int[]。我相信sumOf 期待的是一个元组而不是一个数组。

因此,在 Swift 中,如何将 Array 转换为 Tuple?

【问题讨论】:

  • 该参数不是元组,是可变参数,在函数内部隐式转换为该类型的数组。

标签: arrays swift variadic-functions


【解决方案1】:

这与元组无关。无论如何,在一般情况下不可能从数组转换为元组,因为数组可以有任意长度,并且元组的元组必须在编译时知道。

但是,您可以通过提供重载来解决您的问题:

// This function does the actual work
func sumOf(_ numbers: [Int]) -> Int {
    return numbers.reduce(0, +) // functional style with reduce
}

// This overload allows the variadic notation and
// forwards its args to the function above
func sumOf(_ numbers: Int...) -> Int {
    return sumOf(numbers)
}

sumOf(2, 5, 1)

func averageOf(_ numbers: Int...) -> Int {
    // This calls the first function directly
    return sumOf(numbers) / numbers.count
}

averageOf(2, 5, 1)

也许有更好的方法(例如,Scala 使用特殊类型归属来避免需要重载;您可以在 averageOf 中使用 Scala sumOf(numbers: _*) 编写而不定义两个函数),但我还没有找到在文档中。

【讨论】:

  • 怎么和元组没有关系呢? OP 正在尝试将元组传递给函数。
  • @68cherries OP 搞错了元组是什么。这解决了他的实际问题。
  • 我假设函数将一个元组作为它们的参数列表。这不是真的吗?
  • 没有。可变参数由数组包装。
  • 也很想知道在scala中是否有_*的推论
【解决方案2】:

从 Swift 4.1(在 Xcode 9.2 中)开始,无需使用 sumOf(_ numbers: Int...) 重载,转发可变参数的函数将隐式将其更改为数组的单个参数单个参数。例如。以下代码无需重载即可工作:

// This function does the actual work
func sumOf(_ numbers: [Int]) -> Int {
    return numbers.reduce(0, +) // functional style with reduce
}

func averageOf(_ numbers: Int...) -> Int {
    // This calls the first function directly
    return sumOf(numbers) / numbers.count
}

打印(averageOf(2, 5, 1))

不知道是不是编译器的bug:)

【讨论】:

  • 这是故意的;可变参数以数组形式提供。
【解决方案3】:

我意识到这是一篇较旧的帖子,但它在搜索结果中的排名很高,我找到了一个可行的解决方案。

您可以编写 sumOf 函数以接受整数数组作为数字参数,并重载 sumOf 函数以接受将作为数组传递给第一个版本的数字参数的可变参数输入。这样,averageOf 函数可以将其可变参数输入作为数组传递给 sumOf。

这似乎不太理想,因为您需要重载每个像这样工作的函数,但它会以您想要的方式工作。

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

// Function 1
func sumOf(numbers: Int...) -> Int {
    return sumOf(numbers: numbers)
}
// Example Usage
sumOf(2, 5, 1)

// Function 2
func averageOf(numbers: Int...) -> Int {
    return sumOf(numbers: numbers) / numbers.count
}

【讨论】:

    【解决方案4】:

    我认为他不需要使用 .reduce。相反,只需更改他的 sumOf 函数中的参数定义。而不是:

    func sumOf(numbers: Int...) -> Int {
        var sum = 0
        for number in numbers {
            sum += number
        }
        return sum
    }
    

    写:

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

    【讨论】:

    • 这不是一个好的解决方案,因为我希望用户能够调用函数的可变参数版本(需要调用语法)。
    猜你喜欢
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    相关资源
    最近更新 更多