Передача массива функции с переменным числом аргументов в Swift

В Быстрый язык программирования, он говорит:

Функции также могут принимать переменное количество аргументов, собирая их в массив.

  func sumOf(numbers: Int...) -> Int {
      ...
  }

Когда я вызываю такую ​​функцию с разделенным запятыми списком чисел (`sumOf (1, 2, 3, 4), они становятся доступными как массив внутри функции.

Вопрос: что, если у меня уже есть массив чисел, который я хочу передать этой функции?

let numbers = [1, 2, 3, 4]
sumOf(numbers)

Это не удается с ошибкой компилятора: "Не удалось найти перегрузку для" __conversion ", которая принимает предоставленные аргументы". Есть ли способ превратить существующий массив в список элементов, которые я могу передать вариационной функции?

Ответ 1

Splatting еще не в языке, что подтверждается разработчиками. Обходной путь на данный момент заключается в использовании перегрузки или ожидания, если вы не можете добавить перегрузки.

Ответ 2

Вот работа, которую я нашел. Я знаю, что это не совсем то, что вы хотите, но, похоже, работает.

Шаг 1: Объявите функцию, которую вы хотите, с массивом вместо вариативных аргументов:

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

Шаг 2: Вызовите это из вашей вариационной функции:

func sumOf(numbers: Int...) -> Int {
    return sumOf(numbers)
}

Шаг 3: Позвонить любым путем:

var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])

Кажется странным, но он работает в моих тестах. Дайте мне знать, если это вызовет непредвиденные проблемы для всех. Кажется, что Swift может отделить разницу между двумя вызовами с тем же именем функции.

Кроме того, с помощью этого метода, если Apple обновит язык, как предлагает @manojid ответ, вам нужно будет только обновить эти функции. В противном случае вам придется пройти и много переименовать.

Ответ 3

Вы можете использовать функцию:

typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])

Ответ 4

Вы можете использовать вспомогательную функцию как таковую:

func sumOf (numbers : [Int])  -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }

Ответ 5

Я знаю, что этот ответ не отвечает на ваш точный вопрос, но я чувствую, что его стоит отметить. Я тоже начал играть со Свифтом и сразу столкнулся с подобным вопросом. Ответ Manojlds лучше для вашего вопроса, я согласен, но опять же, еще одно обходное решение, с которым я столкнулся. Мне тоже нравится, как Логан.

В моем случае я просто хотел передать массив:

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

var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])

Просто хотел поделиться, на тот случай, если бы кто-то думал, как я. Большую часть времени я бы предпочел передать массив, как это, но я не думаю, что "Быстро" еще.:)

Ответ 6

Я сделал это (Wrapper + Identity Mapping):

func addBarButtonItems(types: REWEBarButtonItemType...) {
    addBarButtonItems(types: types.map { $0 })
}

func addBarButtonItems(types: [REWEBarButtonItemType]) {
    // actual implementation
}

Ответ 7

Я использую inout для передачи функции array.

препятствиеUnlockArray - моя общедоступная переменная. Обычно у меня есть несколько общедоступных переменных.

unlock(unlockArray: &obstacleUnlockArray)

func unlock(unlockArray:inout [Int]) {
    // modify array
    unlockArray.append(1)
}