web-dev-qa-db-fra.com

Passer un tableau à une fonction avec un nombre variable d'arguments dans Swift

Dans Le Swift Langage de Programmation , il est écrit:

Les fonctions peuvent également prendre un nombre variable d'arguments, en les rassemblant dans un tableau.

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

Lorsque j'appelle une telle fonction avec une liste de nombres séparés par des virgules (`sumOf (1, 2, 3, 4)), ils sont rendus disponibles sous la forme d'un tableau dans la fonction.

Question: que se passe-t-il si j'ai déjà un tableau de nombres que je veux transmettre à cette fonction?

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

Cela échoue avec une erreur du compilateur, "Impossible de trouver une surcharge pour '__conversion' qui accepte les arguments fournis". Existe-t-il un moyen de transformer un tableau existant en une liste d’éléments que je peux transmettre à une fonction variadique?

139
Ole Begemann

Les éclaboussures ne sont pas encore dans la langue , comme le confirment les développeurs. La solution pour l'instant consiste à utiliser une surcharge ou à attendre si vous ne pouvez pas ajouter de surcharge.

87
manojlds

Voici un travail autour que j'ai trouvé. Je sais que ce n'est pas exactement ce que vous voulez, mais cela semble fonctionner.

Étape 1: Déclarez la fonction souhaitée avec un tableau au lieu d’arguments variadiques:

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

Étape 2: Appelez ceci depuis votre fonction variadique:

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

Étape 3: Appelez de toute façon:

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

Cela semble étrange, mais cela fonctionne dans mes tests. Faites-moi savoir si cela cause des problèmes imprévus à quiconque. Swift semble pouvoir séparer la différence entre les deux appels ayant le même nom de fonction.

De plus, avec cette méthode, si Apple met à jour le langage comme le suggère la réponse de @ manojid, il vous suffira de mettre à jour ces fonctions. Sinon, vous devrez procéder à de nombreux changements de nom.

59
Logan

Vous pouvez lancer la fonction:

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

Vous pouvez utiliser une fonction d'assistance en tant que telle:

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

J'ai fait ceci (Wrapper + Identity Mapping):

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

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

Je sais que cette réponse ne répond pas à votre question exacte, mais j'estime qu'il vaut la peine de la noter. Moi aussi, je commençais à jouer avec Swift et j'ai immédiatement rencontré une question similaire. Manojlds répond mieux à votre question, je suis d’accord, mais encore une fois, une autre solution que j’ai trouvée. Il se trouve que j'aime mieux Logan aussi.

Dans mon cas, je voulais juste passer un tableau:

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])

Je voulais juste partager, au cas où quelqu'un penserait comme moi. La plupart du temps, je préférerais passer le tableau de cette manière, mais je ne pense pas encore "Swiftly". :)

1
gregthegeek