¿Cuál es el representante de subrayado _ en las referencias de Swift?

144

En la sección de referencia de los documentos de Apple hay muchas instancias de este tipo de cosas:

func runAction(_action: SKAction!)

El 'equivalente' del objetivo C de esto es:

- (void)runAction:(SKAction *)action

Me sorprende que probablemente sea importante que (en la referencia de Swift) haya un espacio después del guión bajo y la "acción" esté escrita en cursiva.

Pero no puedo entender lo que esto está tratando de transmitir. Entonces, tal vez la pregunta es ... ¿hay alguna referencia para las convenciones utilizadas en las referencias?

- Aquí está la página a la que me refiero en esta referencia para el uso de subrayado: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

Actualizar

Swift 3 ha realizado algunos cambios en cómo se usan y nombran los nombres de parámetros de función / método y las etiquetas de argumento. Esto tiene ramificaciones en esta pregunta y su respuesta. @Rickster hace un trabajo increíble al responder una pregunta diferente sobre _coincidencia en funciones que aclara gran parte de esto, aquí: ¿Por qué necesito guiones bajos rápidamente?

Confuso
fuente
3
Etiquetado con [underscore.js] ??
Martin R
3
La documentación sigue la convención matemática de usar cursiva para nombres de variables. Por ejemplo: sin² a + cos² a = 1.
rob mayoff

Respuestas:

116

Ambas respuestas fueron correctas, pero quiero aclarar un poco más.

_se utiliza para modificar el comportamiento del nombre del parámetro externo para los métodos .

En la sección Nombres de parámetros locales y externos para métodos de la documentación, dice:

Swift le da al primer nombre de parámetro en un método un nombre de parámetro local de manera predeterminada, y le da al segundo nombre y a los nombres de parámetro posteriores nombres de parámetro locales y externos de manera predeterminada.

Por otro lado, las funciones por defecto no tienen nombres de parámetros externos.

Por ejemplo, tenemos este foo()método definido en la clase Bar:

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

Cuando llamas foo(), se llama como bar.foo("Hello", s2: "World").

Pero , puede anular este comportamiento al usarlo _delante de s2donde se declara.

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

Luego, cuando llame foo, podría simplemente llamarse como bar.foo("Hello", "World")sin el nombre del segundo parámetro.

Volviendo a su caso, runActiones un método porque está asociado con el tipo SKNode, obviamente. Por lo tanto, poner un _parámetro antes le actionpermite llamar runActionsin un nombre externo.

Actualización para Swift 2.0

La función y el método ahora funcionan de la misma manera en términos de declaración de nombre de argumento local y externo.

Las funciones ahora se invocan utilizando el nombre del parámetro externo de forma predeterminada, comenzando en el segundo parámetro. Esta regla solo se aplica al código Swift puro.

Entonces, al proporcionar un _frente a una función , la persona que llama no tendrá que especificar el nombre del parámetro externo, al igual que lo que haría para un método .

Aaron He
fuente
9
Confundido, si _escribe antes del segundo parámetro, su respuesta es claramente suficiente; ¿Qué pasa si en func runAction(_action: SKAction!), el _está antes del primer parámetro o si escribe el siguiente código func foo(_ s1: String) { // your code }Xcode le daría una advertencia, pero hay un código de lote como func bringSubviewToFront(_ view: UIView)en la referencia, ¿por qué?
Will Zhang
10
Básicamente, hace esto sin razón y simplemente confunde a todos. increíble.
botbot
2
Un guión bajo se conoce como el 'Patrón comodín' developer.apple.com/library/ios/documentation/Swift/Conceptual/…
user2143356
@Wyatt Zhang, dice el documento, que el uso del _primer parámetro es extraño. Puedo suponer que los diseñadores piensan que obviamente es suficiente para su código y no mejora la legibilidad, sino todo lo contrario, ensucia el código. Entonces recibes la advertencia. La referencia tiene el objetivo opuesto: debe ser lo más claro posible, por lo que se menciona el guión bajo del primer parámetro para CADA método. Eso explicaría todo)
Dmitry Gryazin
44
Es importante tener en cuenta que Swift 3.0 cambia las cosas. Se requieren todas las etiquetas, a menos que especifique lo contrario. Entonces el -antes del primer parámetro ya no es extraño. Por ejemplo: override func viewWillAppear(_ animated: Bool)indica que la persona que llama (código Objective-C) no usará una etiqueta de parámetro
Sr. T
85

El guión bajo es un token general utilizado para indicar un valor descartado.

En este caso específico, significa que la función se invocará como en runAction(argument)lugar derunAction(action:argument)

En otros contextos tiene otro significado similar, por ejemplo, en:

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

Significa que simplemente queremos ejecutar el bloque 5 veces y no nos importa el índice dentro del bloque.

En este contexto:

let (result, _) = someFunctionThatReturnsATuple()

Significa que no nos importa cuál es el segundo elemento de la tupla, solo el primero.

David Berry
fuente
Entonces, ¿en este caso el argumento (una acción) es una opción?
Confundido
1
No, hace que el nombre del parámetro externo (acción :) en este caso esté vacío, por lo que se omite. El argumento aún es obligatorio, simplemente no está etiquetado con acción:
David Berry
44
La respuesta real es una combinación de la respuesta de @ dasblinkenlight y la mía. Él aborda este caso específico con mayor precisión, mientras que el mío aborda la pregunta más amplia, ¿qué significa _?
David Berry
44
Puede usar el signo de descarte también para números muy grandes para que sean más legibles de esta maneralet pi = 3.141_592_653_59
SMP
de manera divertida, también puede usarlo para hacer que los números muy grandes sean menos legibles, comolet pi = 3.1_4_15_92___63
David Berry el
15

Desde Swift 3, todas las etiquetas de argumentos son necesarias de forma predeterminada .

Puede forzar un IDE para ocultar una etiqueta de argumento _.

func foo(a: String) {
}

func foo2(_ a: String) {
}

llamado foo(a: "abc")yfoo2("abc")

Nota: Esto solo se puede usar cuando aes la etiqueta del argumento (externo) y el nombre de la variable (interna) al mismo tiempo. Es equivalente func foo(a a: String), no acepta el _.

¿Por qué lo está usando Apple?

Puedes ver que Apple lo está utilizando en toda la API. Las bibliotecas de Apple todavía están escritas en Objective-C (de lo contrario, comparten los mismos nombres de función de todos modos, que fueron diseñados para la sintaxis de Objective-C)

Funciones como applicationWillResignActive(_ application: UIApplication)tendrían un nombre de parámetro redundanteapplication , ya que ya existe la aplicación en su nombre de función.

Su ejemplo

func runAction(_ action: SKAction!)se llamaría sin su _marca como runAction(action:). El nombre del parámetro actionsería redundante ya que ya hay uno en el nombre de la función. Ese es el propósito y por qué está ahí.

Jakub Truhlář
fuente
13

Un identificador delante de la declaración de parámetro define un nombre de parámetro externo . Este es el nombre que debe proporcionar la persona que llama al llamar a la función:

func someFunction(externalParameterName localParameterName: Int)

Swift proporciona un nombre externo automático para cualquier parámetro predeterminado que defina, si no proporciona un nombre externo usted mismo. El uso de un guión bajo para el nombre del parámetro externo se excluye de este comportamiento:

Puede optar por este comportamiento escribiendo un guión bajo ( _) en lugar de un nombre externo explícito cuando defina el parámetro.

Puede leer más sobre este comportamiento en la sección de Nombres externos para parámetros con valores predeterminados aquí .

dasblinkenlight
fuente
así que ... déjame ver si mi tontería ha acertado. En este ejemplo, debería nombrar mi parámetro variable / constante como "acción" y asignarlo a la SKAction que quiero ejecutar con esta función, y Swift automáticamente nombra el parámetro predeterminado requerido "acción". SIN EMBARGO, si quiero nombrar esta acción de forma personalizada, ¿debo usar el guión bajo en la llamada de la función?
Confundido el
44
@ Confundido Entiendo que SKlos diseñadores no quieren que escriba actiondos veces, porque "acción" ya es parte del nombre de la función. En otras palabras, no quieren que escribas sprite.runAction(action:moveGroundSpritesForever). El propósito de los nombres de parámetros externos era hacer que su código "se lea como una oración"; usar actiondos veces sería contrario al propósito de eso.
dasblinkenlight
Se encendieron algunas luces en la oscuridad. Creo que lo entiendo. Esta característica del lenguaje está diseñada para hacer que las funciones de llamada en Swift se parezcan mucho a cómo llamaría a un método con parámetros en Objective-C. Tal vez.
Confundido
1
Sin embargo, el guión bajo se puede usar para optar de alguna manera por no tener estos nombres de parámetros externos para los parámetros definidos con un valor predeterminado ... todavía no he visto cómo se hace. Seguirá buscando.
Confundido el
Entonces, en resumen, simplemente cambia entre los parámetros con nombre y los parámetros ordinales, por lo que puede alternar fácilmente entre foo.bar(param: 'fiddle') y foo.bar('fiddle') NOTA: con solo un argumento realmente no se vuelve aparente ... pero con múltiples argumentos se vuelve muy relevante: foo.bar(param1: 'fiddle', param2: 'dee') vs foo.bar('fiddle','dee')
jrypkahauer
10

Creo que esto obliga a una convención en Swift que lo hace leer más cerca del objetivo-c, que coincide mejor con las convenciones del cacao. En objc no nombra (externamente) su primer parámetro. En cambio, por convención, generalmente incluye el nombre externo en la última parte del nombre del método de esta manera:

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

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

Para hacer que las llamadas a la API de Swift sean coherentes con objc, deberá suprimir el nombre del parámetro externo del primer parámetro.

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

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")
smileBot
fuente
2
Me gusta esta explicación habiendo aprendido Obj-C primero, has aclarado las cosas. También destaca la importancia de nombrar el Método de manera apropiada en Swift, es decir, la última parte del nombre del Método debe describir el primer argumento, como suele ser el caso en Obj-C. buen material.
rrrrrraul
5

En realidad, hay una diferencia entre el código real utilizado para definir un método y la declaración del método en los documentos de Apple. Tomemos UIControl 's - addTarget: action: forControlEvents: método por ejemplo, el código real es: ingrese la descripción de la imagen aquí

Pero en documentos, aparece así (aviso _ antes del objetivo): ingrese la descripción de la imagen aquí

En el código real, _ se utiliza para hacer que el nombre externo del segundo parámetro o posterior no aparezca cuando se llama a un método, mientras que en documentos, _ antes del nombre local de un parámetro indica que cuando se llama a un método o una función, no debe proporcionar un nombre externo

No hay un nombre externo cuando se llama a una función de manera predeterminada a menos que proporcione el suyo propio o agregue # antes (sin espacios en blanco) el nombre local de un parámetro, por ejemplo, así es como utilizamos dispatch_after : ingrese la descripción de la imagen aquí

Y en documentos, aparece así (nota tres _): ingrese la descripción de la imagen aquí

La convención de la declaración de la función es la misma que he descrito para el método.

Fujianjin6471
fuente
1

Solo más visualmente.

ingrese la descripción de la imagen aquí

Como puede ver, _simplemente omita un nombre de parámetro local o no.

Nik Kov
fuente