166 votes

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

Sur Le langage de programmation Swift il est dit :

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 mis à disposition sous forme de tableau dans la fonction.

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

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

Cela échoue avec une erreur de compilation, "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 passer à une fonction variadique ?

2 votes

Pourquoi ne pas simplement configurer la fonction pour qu'elle prenne un tableau d'entiers à la place ?

36 votes

Bien sûr, mais je ne suis peut-être pas l'auteur de la fonction et je ne peux pas (ou ne veux pas) la modifier.

0 votes

Ach @OleBegemann me voilà, ne pouvant pas changer la fonction et lisant votre question... Toujours pas de solution... salutations à Berlin

109voto

manojlds Points 96599

Le splatting n'est pas encore dans la langue comme l'ont confirmé les développeurs. La solution pour l'instant est d'utiliser une surcharge ou d'attendre si vous ne pouvez pas ajouter de surcharges.

5 votes

Le splatting est-il déjà dans la langue ? J'essaie d'appeler sumOf(...numbers)

3 votes

Quelle déception ! Je me suis heurté à cela même avec quelque chose d'aussi simple que d'essayer de déléguer mes propres appels de journal vers le bas à print !

73voto

Logan Points 7458

Voici une solution que j'ai trouvée. Je sais que ce n'est pas exactement ce que vous voulez, mais ça semble fonctionner.

Étape 1 : Déclarez la fonction que vous souhaitez 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 cette fonction à partir de votre fonction variadique :

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

Étape 3 : Appelez dans les deux sens :

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 pose des problèmes imprévus à quelqu'un. Swift semble être capable de faire la différence entre les deux appels avec le même nom de fonction.

De plus, avec cette méthode, si Apple met à jour la langue comme le suggère la réponse de @manojid, il vous suffira de mettre à jour ces fonctions. Sinon, vous devrez passer par toutes les étapes et faire beaucoup de renommage.

0 votes

Merci, j'aime cette solution de rechange. Je vais quand même attribuer la "bonne" réponse à manojlds pour avoir trouvé le lien vers la confirmation officielle que la fonctionnalité n'est pas encore disponible. J'espère que vous comprenez.

0 votes

Vous suivez probablement le Guide et votre func sumOf(numbers : [Int]) -> Int calcule en fait la moyenne.

20voto

Guoye Zhang Points 299

Vous pouvez lancer la fonction :

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

17voto

GoZoner Points 15679

Vous pouvez utiliser une fonction d'aide comme telle :

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

17 votes

A condition qu'il existe une version pour les tableaux. Je pensais que le principe de la question était que la fonction originale prenait Int... et ne peut pas être (facilement) modifié ?

2 votes

@delnan : C'est exact. Il me semble qu'il devrait y avoir un moyen de passer un tableau dans une fonction variadique, étant donné que les arguments variadiques sont transformés en tableau de toute façon.

1 votes

Les langages qui acceptent un nombre variable d'arguments dans les fonctions, comme Scheme, ont une fonction apply procédure. J'ai cru comprendre que certaines personnes appellent ça "splatter".

3voto

1101 Points 454

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

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X