Quel est le représentant du _ souligné dans Swift References?


144

Dans la section de référence de la documentation d'Apple, il y a beaucoup d'exemples de ce genre de chose:

func runAction(_action: SKAction!)

L'équivalent Objective-C de ceci est:

- (void)runAction:(SKAction *)action

Il me semble qu'il est probablement important (dans la référence Swift) qu'il y ait un espace après le trait de soulignement et que «action» soit écrit en italique.

Mais je ne peux pas comprendre ce que cela essaie de transmettre. Alors peut-être que la question est ... y a-t-il une référence pour les conventions utilisées dans les références?

- voici la page que je fais référence dans cette référence à l'utilisation du trait de soulignement: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

Mettre à jour

Swift 3 a apporté quelques modifications à la façon dont les noms de paramètres de fonction / méthode et les étiquettes d'argument sont utilisés et nommés. Cela a des ramifications sur cette question et sa réponse. @Rickster fait un travail incroyable en répondant à une question différente sur les _underscores dans des fonctions qui efface une grande partie de cela, ici: Pourquoi ai-je besoin de soulignements dans Swift?


3
Marqué avec [underscore.js] ??
Martin R

3
La documentation suit la convention mathématique d'utilisation de l'italique pour les noms de variables. Par exemple: sin² a + cos² a = 1.
ROB

Réponses:


116

Les deux réponses étaient correctes, mais je veux clarifier un peu plus.

_est utilisé pour modifier le comportement des noms de paramètres externes pour les méthodes .

Dans la section Noms de paramètres locaux et externes pour les méthodes de la documentation, il est dit:

Swift donne au premier nom de paramètre dans une méthode un nom de paramètre local par défaut, et donne au deuxième nom de paramètre et aux suivants des noms de paramètres locaux et externes par défaut.

En revanche, les fonctions par défaut n'ont pas de noms de paramètres externes.

Par exemple, nous avons cette foo()méthode définie dans la classe Bar:

class Bar{
    func foo(s1: String, s2: String) -> String {
        return s1 + s2;
    }
}

Lorsque vous appelez foo(), il est appelé comme bar.foo("Hello", s2: "World").

Mais vous pouvez remplacer ce comportement en utilisant _devant l' s2endroit où il est déclaré.

func foo(s1: String, _ s2: String) -> String{
    return s1 + s2;
}

Ensuite, lorsque vous appelez foo, il pourrait être simplement appelé comme bar.foo("Hello", "World")sans le nom du deuxième paramètre.

Revenons à votre cas, runActionc'est une méthode parce qu'elle est associée au type SKNode, évidemment. Ainsi, mettre un _paramètre avant actionvous permet d'appeler runActionsans nom externe.

Mise à jour pour Swift 2.0

La fonction et la méthode fonctionnent désormais de la même manière en termes de déclaration de nom d'argument local et externe.

Les fonctions sont désormais appelées en utilisant le nom du paramètre externe par défaut, à partir du 2ème paramètre. Cette règle s'applique uniquement au code Swift pur.

Ainsi, en fournissant un _devant une fonction , l'appelant n'aura pas à spécifier le nom du paramètre externe, tout comme ce que vous feriez pour une méthode .


9
Confus, si l' _écriture avant le deuxième paramètre, votre réponse est assez clairement; et si dans func runAction(_action: SKAction!), le _est avant le premier paramètre ou si vous écrivez le code suivant func foo(_ s1: String) { // your code }Xcode vous donnerait un avertissement, mais il y a beaucoup de code comme func bringSubviewToFront(_ view: UIView)dans la référence, pourquoi?
Will Zhang

10
donc fondamentalement, il le fait sans raison et confond tout le monde. impressionnant.
botbot

2
Un trait de soulignement est connu sous le nom de 'Wildcard Pattern' developer.apple.com/library/ios/documentation/Swift/Conceptual/…
user2143356

@Wyatt Zhang, dit le doc, que l'utilisation de _pour le premier paramètre est étrangère. Je peux supposer que les concepteurs pensent que c'est évidemment suffisant pour votre code et n'améliore pas la lisibilité, bien au contraire, cela salit le code. Alors vous recevez l'avertissement. La référence a le but opposé: elle doit être aussi claire que possible - donc le trait de soulignement du premier paramètre est mentionné pour CHAQUE méthode. Cela expliquerait tout)
Dmitry Gryazin

4
Il est important de noter que Swift 3.0 change les choses. Toutes les étiquettes sont obligatoires, sauf indication contraire de votre part. Donc, l' -avant le premier paramètre n'est plus étranger. Par exemple: override func viewWillAppear(_ animated: Bool)signale que l'appelant (code Objective-C) n'utilisera pas d'étiquette de paramètre
M. T

85

Le trait de soulignement est un jeton général utilisé pour indiquer une valeur ignorée.

Dans ce cas précis, cela signifie que la fonction sera invoquée au runAction(argument)lieu derunAction(action:argument)

Dans d'autres contextes, il a une autre signification similaire, par exemple dans:

for _ in 0..<5 { ... }

Cela signifie que nous voulons simplement exécuter le bloc 5 fois et que nous ne nous soucions pas de l'index dans le bloc.

Dans ce contexte:

let (result, _) = someFunctionThatReturnsATuple()

Cela signifie que nous ne nous soucions pas de ce qu'est le deuxième élément du tuple, seulement le premier.


Donc, dans ce cas, l'argument (une action) est une option?
Confus le

1
Non, cela fait que le nom du paramètre externe (action :) dans ce cas, soit vide, donc omis. L'argument est toujours obligatoire, il n'est tout simplement pas balisé avec action :.
David Berry

4
La vraie réponse est une combinaison de la réponse de @ dasblinkenlight et de la mienne. Il aborde ce cas spécifique plus précisément, alors que le mien aborde la question plus large, que signifie _?
David Berry

4
Vous pouvez également utiliser le signe de suppression pour les très gros nombres afin de les rendre plus lisibles comme cecilet pi = 3.141_592_653_59
SMP

amusant, vous pouvez également l'utiliser pour rendre de très grands nombres moins lisibles, commelet pi = 3.1_4_15_92___63
David Berry

15

Depuis Swift 3, toutes les étiquettes d'argument sont requises par défaut .

Vous pouvez forcer un IDE à masquer une étiquette d'argument avec _.

func foo(a: String) {
}

func foo2(_ a: String) {
}

appelé foo(a: "abc")etfoo2("abc")

Remarque: Cela ne peut être utilisé que lorsque ale nom de l'argument (externe) et le nom de la variable (interne) sont en même temps. C'est équivalent - func foo(a a: String)n'acceptera pas le _.

Pourquoi Apple l'utilise-t-il?

Vous pouvez voir qu'Apple l'utilise dans l'API. Les bibliothèques d'Apple sont toujours écrites en Objective-C (sinon, elles partagent de toute façon les mêmes noms de fonction, qui ont été conçus pour la syntaxe Objective-C)

Des fonctions comme applicationWillResignActive(_ application: UIApplication)auraient un nom de paramètre redondantapplication , car il y a déjà l' application dans son nom de fonction.

Votre exemple

func runAction(_ action: SKAction!)serait appelé sans sa _marque comme runAction(action:). Le nom du paramètre actionserait redondant car il y en a déjà un dans le nom de la fonction. C'est le but et pourquoi il est là.


13

Un identifiant devant la déclaration de paramètre définit un nom de paramètre externe . C'est le nom qui doit être fourni par l'appelant lors de l'appel de la fonction:

func someFunction(externalParameterName localParameterName: Int)

Swift fournit un nom externe automatique pour tout paramètre par défaut que vous définissez, si vous ne fournissez pas vous-même un nom externe. L'utilisation d'un trait de soulignement pour le nom du paramètre externe exclut ce comportement:

Vous pouvez désactiver ce comportement en écrivant un trait de soulignement ( _) au lieu d'un nom externe explicite lorsque vous définissez le paramètre.

Vous pouvez en savoir plus sur ce comportement dans la section sur les noms externes pour les paramètres avec des valeurs par défaut ici .


alors ... laissez-moi voir si mon manque d'esprit a raison. Dans cet exemple, je devrais nommer ma variable / constante de paramètre comme "action" et l'affecter à la SKAction que je souhaite exécuter par cette fonction, et Swift nomme automatiquement le paramètre par défaut requis "action". CEPENDANT, si je veux personnaliser le nom de cette action, je dois utiliser le trait de soulignement dans l'appel de la fonction?
Confus le

4
@Confused Je crois comprendre que SKles concepteurs ne veulent pas que vous écriviez actiondeux fois, car "action" fait déjà partie du nom de la fonction. En d'autres termes, ils ne veulent pas que vous écriviez sprite.runAction(action:moveGroundSpritesForever). Le but des noms de paramètres externes était de rendre votre code "lu comme une phrase"; utiliser actiondeux fois irait à l'encontre du but de cela.
dasblinkenlight

Certaines lumières se sont allumées dans l'obscurité. Je pense que je comprends. Cette fonctionnalité du langage est destinée à faire en sorte que les fonctions d'appel dans Swift ressemblent beaucoup à la façon dont vous appelleriez une méthode avec des paramètres en Objective-C. Peut être.
Confus le

1
Cependant, le trait de soulignement peut être utilisé pour choisir de ne pas avoir ces noms de paramètres externes pour des paramètres définis avec une valeur par défaut ... Continuera à chercher.
Confus le

Donc ... en bref, il bascule simplement entre les paramètres nommés et les paramètres ordinaux, vous pouvez donc facilement basculer entre foo.bar(param: 'fiddle') et foo.bar('fiddle') REMARQUE: avec un seul argument, cela ne devient vraiment pas apparent ... mais avec plusieurs arguments, cela devient très pertinent: foo.bar(param1: 'fiddle', param2: 'dee') vs foo.bar('fiddle','dee')
jrypkahauer

10

Je pense que cela force une convention dans Swift qui la rend plus proche de l'objectif-c, qui correspond mieux aux conventions du cacao. Dans objc, vous ne nommez pas (en externe) votre premier paramètre. Au lieu de cela, par convention, vous incluez généralement le nom externe dans la dernière partie du nom de la méthode comme ceci:

- (void)myFancyMethodWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName;

[someInstance myFancyMethodWithFirstName:@"John" lastName:@"Doe"];

Pour rendre les appels d'API Swift cohérents avec objc, vous souhaiterez supprimer le nom de paramètre externe du premier paramètre.

func myFancyMethodWithFirstName(_ firstName:String, lastName:String);

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")

2
J'aime cette explication. après avoir appris Obj-C en premier, vous avez clarifié les choses. Il souligne également l'importance de nommer la méthode de manière appropriée dans Swift, à savoir que la dernière partie du nom de la méthode doit décrire le premier argument, comme c'est généralement le cas dans Obj-C. Bon produit.
rrrrrraul

5

En fait, il existe une différence entre le code réel utilisé pour définir une méthode et la déclaration de méthode dans la documentation d'Apple. Prenons UIControl de - addTarget: action: forControlEvents: méthode par exemple, le code est réel: entrez la description de l'image ici

Mais dans la documentation, cela ressemble à ceci (remarquez _ avant la cible): entrez la description de l'image ici

Dans le code réel, _ est utilisé pour que le nom externe du deuxième paramètre ou des suivants n'apparaisse pas lorsqu'une méthode est appelée, tandis que dans la documentation, _ avant que le nom local d'un paramètre indique que lorsque vous appelez une méthode ou une fonction, vous ne devez pas fournir de nom externe.

Il n'y a pas de nom externe lorsqu'une fonction est appelée par défaut, sauf si vous fournissez le vôtre ou ajoutez le # avant (sans espace) le nom local d'un paramètre, par exemple, voici comment nous utilisons dispatch_after : entrez la description de l'image ici

Et dans la documentation, cela ressemble à ceci (notez trois _): entrez la description de l'image ici

La convention de déclaration de fonction est exactement la même que celle que j'ai décrite pour method.


1

Juste plus visuellement.

entrez la description de l'image ici

Comme vous pouvez le voir, _faites simplement omettre un nom de paramètre local ou non.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.