81 votes

Swift : étiquette d'argument manquante 'xxx' dans l'appel

func say(name:String, msg:String) {
    println("\(name) say \(msg)")
}

say("Henry","Hi,Swift")  <---- error because missing argument label 'msg' in call

Je dois utiliser

   say("Henry",msg:"Hi,Swift")

Pourquoi ? Si je mets plus de deux var dans le func de sorte que je dois écrire le nom de la var au lieu de la première var quand j'appelle ce func
C'est vraiment un problème, et je ne vois pas d'explication dans le tutoriel iBook Swift.

2 votes

Le nom de votre fonction est "say" et pourtant vous appelez sayHello ??

1 votes

Éventuellement en rapport : stackoverflow.com/questions/24049272/

0 votes

J'ai déjà vu cette question, mais elle n'a pas résolu mon problème.

72voto

Logan Points 7458

L'une des raisons possibles est qu'il s'agit en fait d'une méthode. Les méthodes sont très sournoises, elles ressemblent à des fonctions normales, mais elles n'agissent pas de la même manière :

func funFunction(someArg: Int, someOtherArg: Int) {
    println("funFunction: \(someArg) : \(someOtherArg)")
}

// No external parameter
funFunction(1, 4)

func externalParamFunction(externalOne internalOne: Int, externalTwo internalTwo: Int) {
    println("externalParamFunction: \(internalOne) : \(internalTwo)")
}

// Requires external parameters
externalParamFunction(externalOne: 1, externalTwo: 4)

func externalInternalShared(#paramOne: Int, #paramTwo: Int) {
    println("externalInternalShared: \(paramOne) : \(paramTwo)")
}

// The '#' basically says, you want your internal and external names to be the same

// Note that there's been an update in Swift 2 and the above function would have to be written as:

func externalInternalShared(paramOne paramOne: Int, #paramTwo: Int) {
    print("externalInternalShared: \(paramOne) : \(paramTwo)")
}

externalInternalShared(paramOne: 1, paramTwo: 4)

Maintenant, voici la partie amusante, déclarer une fonction à l'intérieur d'une classe et ce n'est plus une fonction ... c'est une méthode.

class SomeClass {
    func someClassFunctionWithParamOne(paramOne: Int, paramTwo: Int) {
        println("someClassFunction: \(paramOne) : \(paramTwo)")
    }
}

var someInstance = SomeClass()
someInstance.someClassFunctionWithParamOne(1, paramTwo: 4)

Cela fait partie de la conception du comportement des méthodes.

Apple Docs :

Plus précisément, Swift attribue par défaut au premier nom de paramètre d'une méthode un nom de paramètre local, et attribue par défaut au deuxième nom de paramètre et aux suivants des noms de paramètres à la fois locaux et externes. Cette convention correspond à la convention de nommage et d'appel typique que vous connaissez pour avoir écrit des méthodes en Objective-C, et permet des appels de méthode expressifs sans avoir besoin de qualifier vos noms de paramètres.

Remarquez l'autocomplétion : enter image description here

0 votes

Il est amusant de constater que le fait de ne pas fournir le nom du deuxième paramètre dans le terrain de jeu semble fonctionner à merveille !

1 votes

@user1107173 - C'est parce que c'est hors du contexte d'une classe. Si vous le placez à l'intérieur d'une classe, il fournira le nom du second paramètre. Playground n'a rien à voir avec cela :)

0 votes

Ce n'est plus le cas depuis Swift 2.1. Les fonctions et les méthodes partagent désormais exactement la même sémantique pour les étiquettes de paramètres, à l'exception des étiquettes spéciales de type init des méthodes. Voir aussi cette réponse .

11voto

ephemera Points 2690

Il s'agit simplement d'une influence du langage Objective-C. Lors de l'appel d'une méthode, le premier paramètre d'une méthode ne doit pas être explicitement étiqueté (car en Objective-C, il est effectivement "étiqueté" par le nom de la méthode). Cependant, tous les paramètres suivants ont besoin d'un nom pour les identifier. Ils peuvent également prendre un nom local (facultatif) à utiliser dans la méthode elle-même (voir le lien de Jiaaro dans les commentaires ci-dessus).

2 votes

J'ai l'impression qu'au lieu de dire "n'a pas besoin d'être explicitement étiqueté", nous pourrions dire "ne peut pas être étiqueté" parce que l'ajout d'une étiquette à cet endroit entraînera une erreur de compilation.

8voto

Fortran Points 434

Simple :

Mauvaise syntaxe des fonctions d'appel (ce n'est pas la même chose en c/c++/java/c#)

C'est faux :

say("Henry")

Correct :

say(name:"Henry")

PS : Vous devez toujours ! ajouter " nom fonction paramètre " avant la valeur.

3voto

Fangming Points 10276

Mise à jour de Swift 3.0 :

Dans swift 3.0, les méthodes avec un nom de paramètre par entrée doivent avoir ce nom de paramètre comme partie intégrante de l'appel de la fonction. Ainsi, si vous définissez la fonction comme ceci

func say(name:String, msg:String) {
    print("\(name) say \(msg)")
}

Votre appel de fonction devra ressembler à ceci

self.say(name: "Henry",msg: "Hi,Swift")

Si vous souhaitez disposer d'étiquettes de fonctions lisibles en anglais, mais que vous ne souhaitez pas modifier le nom des paramètres d'entrée, vous pouvez ajouter l'étiquette devant le nom des paramètres, comme suit

func say(somethingBy name:String, whoIsActuallySaying msg:String) {
    print("\(name) say \(msg)")
}

Il faut ensuite l'appeler comme suit

self.say(somethingBy: "Henry",whoIsActuallySaying: "Hi,Swift")

1voto

user3386109 Points 7228

Il s'agit d'une bizarrerie du compilateur. Les fonctions (qui ne sont pas membres d'une classe) et les méthodes de classe ont un comportement par défaut différent en ce qui concerne les paramètres nommés. Ceci est cohérent avec le comportement des paramètres nommés en Objective-C (mais n'a pas de sens pour quelqu'un qui débute avec Swift et qui n'a pas d'expérience avec Objective-C).

Voici ce que dit la référence du langage à propos des paramètres nommés pour les fonctions (en particulier les paramètres pour lesquels aucun nom externe n'est donné et qui n'ont pas de valeur par défaut)

Toutefois, ces noms de paramètres ne sont utilisés que dans le cadre de l'application elle-même, et la fonction ne peut pas à utiliser lors de l'appel de la fonction. Ces noms de paramètres sont connus sous le nom de noms de paramètres locaux, parce qu'ils ne sont disponibles qu'à l'appel de la fonction. ils ne peuvent être utilisés que dans le corps de la fonction.

Pour plus d'informations sur les méthodes de classe, voir la réponse de Logan.

0 votes

En fait, ce n'est pas si simple. Si vous lisez plus loin dans la documentation, il y a des moments où le nom interne est automatiquement transformé en nom externe, d'après ce que je me souviens, c'est principalement dans les définitions de classe, les balises 2 et suivantes sont requises par défaut.

4 votes

@David Je suis d'accord, ma réponse couvre le cas où les func est en fait une fonction. La réponse de Logan couvre le cas où la fonction func est en fait une méthode. Personnellement, je n'aime pas ce choix de conception de la part d'Apple. La syntaxe d'appel des fonctions/méthodes doit être cohérente, quel que soit le contexte. Les programmeurs peuvent utiliser la syntaxe # pour forcer l'utilisation des noms de paramètres comme une question de style.

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