220 votes

Pourquoi ai-je besoin de traits de soulignement dans Swift?

Ici, dit-il, "Remarque: l' _ signifie "je ne m'inquiète pas au sujet de cette valeur"", mais de venir à partir de JavaScript, je ne comprends pas ce que cela signifie.

La seule façon que je peux obtenir ces fonctions pour imprimer en utilisant le souligne avant les paramètres:

func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(7, 3))
print(divmod(5, 2))
print(divmod(12,4))

Sans le souligne, je dois l'écrire comme ceci afin d'éviter toutes erreurs:

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(a: 7, b: 3))
print(divmod(a: 5, b: 2))
print(divmod(a: 12,b: 4))

Je ne comprends pas ce trait de soulignement d'utilisation. Quand, comment et pourquoi dois-je utiliser ces caractères de soulignement?

458voto

rickster Points 19870

Il y a quelques nuances à différents cas d'utilisation, mais en général, un trait de soulignement signifie "ignorer".


Lors de la déclaration d'une nouvelle fonction, un trait de soulignement indique Swift que le paramètre doit avoir aucune étiquette lorsqu'elle est appelée - c'est le cas, vous voyez. Une meilleure déclaration de la fonction ressemble à ceci:

func myFunc(label name: Int) // call it like myFunc(label: 3)

"label" est un argument de l'étiquette, et doit être présent lorsque vous appelez la fonction. (Et depuis Swift 3, les étiquettes sont requis pour tous les arguments par défaut.) "nom" est le nom de la variable pour que l'argument que vous utilisez à l'intérieur de la fonction. Une forme courte ressemble à ceci:

func myFunc(name: Int) // call it like myFunc(name: 3)

C'est un raccourci qui vous permet d'utiliser le même mot pour les deux externes argument de l'étiquette et interne de nom de paramètre. Il est équivalent à func myFunc(name name: Int).

Si vous voulez que votre fonction pour être appelée sans paramètre étiquettes, vous utilisez le trait de soulignement _ pour que l'étiquette soit rien/ignorés. (Dans ce cas, vous devez fournir un nom interne si vous voulez être en mesure d'utiliser le paramètre.)

func myFunc(_ name: Int) // call it like myFunc(3)

Dans une instruction d'affectation, un trait de soulignement signifie "ne pas céder à rien". Vous pouvez l'utiliser si vous voulez appeler une fonction qui retourne un résultat, mais ne se soucient pas de la valeur retournée.

_ = someFunction()

Ou, comme dans l'article lié, d'ignorer un élément d'un retour tuple:

let (x, _) = someFunctionThatReturnsXandY()

Lorsque vous écrivez une fermeture qui implémente un type de fonction, vous pouvez utiliser le trait de soulignement à ignorer certains paramètres.

PHPhotoLibrary.performChanges( { /* some changes */ },
    completionHandler: { success, _ in // don't care about error
        if success { print("yay") }
    })

De même, lorsque l'on déclare une fonction qui adopte un protocole ou remplace une super-classe de la méthode, vous pouvez utiliser _ pour le paramètre noms d'ignorer les paramètres. Depuis le protocole/super-classe peut également définir le paramètre n'a pas d'étiquette, vous pouvez même finir par deux caractères de soulignement dans une rangée.

class MyView: NSView {
    override func mouseDown(with _: NSEvent) {
        // don't care about event, do same thing for every mouse down
    }
    override func draw(_ _: NSRect) {
        // don't care about dirty rect, always redraw the whole view
    }
}

En quelque sorte liée à la dernière deux styles: lors de l'utilisation d'un contrôle de flux de construire qui lie une variable/constante, vous pouvez utiliser _ de l'ignorer. Par exemple, si vous souhaitez effectuer une itération à une séquence sans avoir accès à ses membres:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}

Si vous êtes à la liaison n-uplet cas dans une instruction switch, le trait de soulignement peut fonctionner comme un caractère générique, comme dans cet exemple (raccourcie, passant de l'un à L'Swift Langage de Programmation):

switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, \(somePoint.1)) is on the y-axis")
default:
    print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}

Une dernière chose qui n'est pas tout à fait relative, mais qui je vais l'inscrire depuis (comme indiqué par les commentaires) il semble mener les gens d'ici: Un trait de soulignement dans un identificateur - par exemple, var _foo, func do_the_thing(), struct Stuff_ - ne signifie rien en particulier à Swift, mais il a un peu d'usages parmi les programmeurs.

Souligne dans un nom sont un choix de style, mais pas préféré dans la communauté Swift, qui a de fortes conventions sur l'utilisation de UpperCamelCase pour les types et les lowerCamelCase pour tous les autres symboles.

La préfixation ou suffixant un nom de symbole de soulignement est un style de la convention, historiquement utilisé pour la distinction privé/usage interne seulement les symboles exportés à partir de l'API. Cependant, Swift a modificateurs d'accès pour que, si cette convention est généralement considérée comme non-idiomatiques en Swift.

Quelques symboles avec double-trait de soulignement préfixes (func __foo()) se cachent dans les profondeurs de la Pomme de Sdk: ce sont (Obj)C symboles importés dans Swift à l'aide de l' NS_REFINED_FOR_SWIFT d'attribut. Apple utilise que quand ils veulent faire un "plus Swifty" version d'un (Obj)de l'API C - par exemple, pour faire un type indépendant de la méthode dans une méthode générique. Ils ont besoin de l'utilisation de la importées de l'API pour faire de l'raffiné Swift version de travail, de sorte qu'ils utilisent l' __ pour les conserver, tout en cachant à partir de la plupart des outils et de la documentation.

7voto

Caspar Wylie Points 1773

Depuis Swift 3, en précisant les noms des paramètres sur les appels de fonction est devenue obligatoire, même pour la première. Car cela pourrait causer d'énormes problème de code écrit en swift 2, vous pouvez utiliser un caractère de soulignement à la déclaration pour éviter d'avoir à écrire le nom de paramètre dans l'appel. Donc, dans ce cas, il est en train de dire "ne se soucient pas de l'externe nom de paramètre". Externe nom du paramètre est ce que vous appelez les paramètres en dehors de la fonction (sur appel) et non à l'intérieur. Ces noms de paramètres sont appelés argument étiquettes. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ... voir la façon dont le paramètre est donné deux noms? eh bien, la première est celle où le trait de soulignement.Espérons que cela aide, et ne se demander si encore confus.

5voto

davidhu2000 Points 3568
func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

L' _ est un espace réservé pour le nom du paramètre. Dans votre exemple, vous appeler différemment, dans la seconde fonction, vous devez écrire le nom du paramètre a: 1.

Swift est le nom de la fonction de la convention est - funcName(param1:param2:), et il a besoin de l' _ comme un espace réservé pour créer le nom de la fonction.

Dans la première, le nom est

divmod(_:_:)

Alors que la seconde est

divmod(a:b:)

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