¿Por qué necesito guiones bajos en Swift?

Resuelto Michael Rader asked hace 7 años • 4 respuestas

Aquí dice: "Nota: _significa "No me importa ese valor"", pero viniendo de JavaScript, no entiendo lo que eso significa.

La única forma en que puedo imprimir estas funciones es usando guiones bajos antes de los parámetros:

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))

Sin los guiones bajos tengo que escribirlo así para evitar errores:

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))

No entiendo este uso de subrayado. ¿Cuándo, cómo y por qué uso estos guiones bajos?

Michael Rader avatar Sep 22 '16 04:09 Michael Rader
Aceptado

Hay algunos matices en los diferentes casos de uso, pero generalmente un guión bajo significa "ignorar esto".


Al declarar una nueva función, un guión bajo le dice a Swift que el parámetro no debe tener etiqueta cuando se llama; ese es el caso que estás viendo. Una declaración de función más completa se ve así:

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

"etiqueta" es una etiqueta de argumento y debe estar presente cuando se llama a la función. (Y desde Swift 3, se requieren etiquetas para todos los argumentos de forma predeterminada). "nombre" es el nombre de la variable para ese argumento que usa dentro de la función. Una forma más corta se ve así:

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

Este es un atajo que le permite usar la misma palabra tanto para la etiqueta del argumento externo como para el nombre del parámetro interno. Es equivalente a func myFunc(name name: Int).

Si desea que su función sea invocable sin etiquetas de parámetros, use el guión bajo _para que la etiqueta no sea nada o se ignore. (En ese caso, debe proporcionar un nombre interno si desea poder utilizar el parámetro).

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

En una declaración de asignación, un guión bajo significa "no asignar a nada". Puede usar esto si desea llamar a una función que devuelve un resultado pero no le importa el valor devuelto.

_ = someFunction()

O, como en el artículo al que vinculaste, ignorar un elemento de una tupla devuelta:

let (x, _) = someFunctionThatReturnsXandY()

Cuando escribe un cierre que implementa algún tipo de función definido, puede usar el guión bajo para ignorar ciertos parámetros.

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

De manera similar, al declarar una función que adopta un protocolo o anula un método de superclase, puede utilizar nombres_ de parámetros para ignorar los parámetros. Dado que el protocolo/superclase también puede definir que el parámetro no tiene etiqueta, incluso puede terminar con dos guiones bajos seguidos.

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
    }
}

Algo relacionado con los dos últimos estilos: cuando se utiliza una construcción de control de flujo que vincula una variable/constante local, se puede utilizar _para ignorarla. Por ejemplo, si desea iterar una secuencia sin necesidad de acceder a sus miembros:

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

Si está vinculando casos de tupla en una declaración de cambio, el guión bajo puede funcionar como un comodín, como en este ejemplo (abreviado de uno en El lenguaje de programación Swift ):

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")
}

Una última cosa que no está del todo relacionada, pero que incluiré ya que (como se indica en los comentarios) parece llevar a la gente aquí: un guión bajo en un identificador (por ejemplo var _foo, func do_the_thing(), struct Stuff_) no significa nada en particular para Swift, pero tiene algunos usos. entre los programadores.

Los guiones bajos dentro de un nombre son una elección de estilo, pero no son los preferidos en la comunidad Swift, que tiene fuertes convenciones sobre el uso de UpperCamelCase para tipos y lowerCamelCase para todos los demás símbolos.

Colocar un guión bajo como prefijo o sufijo en el nombre de un símbolo es una convención de estilo que se utiliza históricamente para distinguir los símbolos privados/de uso exclusivo interno de la API exportada. Sin embargo, Swift tiene modificadores de acceso para eso, por lo que esta convención generalmente se considera no idiomática en Swift.

Algunos símbolos con prefijos de doble guión bajo ( func __foo()) se esconden en las profundidades de los SDK de Apple: estos son símbolos (Obj)C importados a Swift usando el NS_REFINED_FOR_SWIFTatributo. Apple lo usa cuando quiere crear una versión "más rápida" de una API (Obj)C, por ejemplo, para convertir un método independiente de tipo en un método genérico . Necesitan usar la API importada para que la versión refinada de Swift funcione, por lo que usan __para mantenerla disponible mientras la ocultan de la mayoría de las herramientas y documentación.

rickster avatar Sep 21 '2016 22:09 rickster

Además de la respuesta aceptada, uno de los casos de uso _es cuando necesita escribir un número largo en el código.

Número más legible

🛑 Este no es un texto fácil de leer para humanos:

let x = 1000000000000

✅ Puedes agregar _el número para que sea más legible para los humanos:

let x = 1_000_000_000_000

Interfaces subrayadas

Es posible que te encuentres en algún lugar de Swift donde las interfaces comienzan con _. Aunque técnicamente están declarados public, comienzan con un guión bajo NO se consideran parte de la interfaz pública de este paquete. Podemos eliminarlos o cambiarlos en cualquier versión sin previo aviso, incluidas las versiones menores.

Por ejemplo @_exportedImporto muchos más ejemplos aquí en el repositorio oficial de Swift Collections

⚠️ Simplemente no los uses o deberás realizar un seguimiento manual de los cambios.

Mojtaba Hosseini avatar Nov 01 '2019 21:11 Mojtaba Hosseini

Desde Swift 3, especificar nombres de parámetros en llamadas a funciones se ha vuelto obligatorio, incluso para la primera. Entonces, debido a que eso podría causar un gran problema al código escrito en Swift 2, puede usar un guión bajo en la declaración para evitar tener que escribir el nombre del parámetro durante la llamada. Entonces, en este caso, dice "no me importa el nombre del parámetro externo". Donde el nombre del parámetro externo es lo que usted llama a los parámetros fuera de la función (de llamada), no dentro. Estos nombres de parámetros externos se denominan etiquetas de argumentos. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thinkts /... ¿ves cómo al parámetro se le dan dos nombres? Bueno, el primero es hacia dónde va el guión bajo. Espero que esto ayude y pregunte si todavía está confundido.

Caspar Wylie avatar Sep 21 '2016 21:09 Caspar Wylie