Perché ho bisogno di trattini bassi in rapido?


161

Qui dice "Nota: _significa" Non mi interessa quel valore "", ma proviene da JavaScript, non capisco cosa significhi.

L'unico modo per ottenere queste funzioni per la stampa è stato utilizzando i trattini bassi prima dei parametri:

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

Senza i trattini bassi devo scriverlo in questo modo per evitare errori:

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

Non capisco questo carattere di sottolineatura. Quando, come e perché utilizzo questi trattini bassi?

Risposte:


354

Esistono alcune sfumature per i diversi casi d'uso, ma in genere un carattere di sottolineatura significa "ignora questo".


Quando si dichiara una nuova funzione, un carattere di sottolineatura indica a Swift che il parametro non dovrebbe avere un'etichetta quando viene chiamato - è il caso che si vede. Una dichiarazione di funzione più completa è simile alla seguente:

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

"etichetta" è un'etichetta argomento e deve essere presente quando si chiama la funzione. (E dal momento che Swift 3, le etichette sono obbligatorie per tutti gli argomenti per impostazione predefinita.) "Name" è il nome della variabile per quell'argomento che usi all'interno della funzione. Una forma più corta si presenta così:

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

Questa è una scorciatoia che ti consente di usare la stessa parola sia per l'etichetta dell'argomento esterno che per il nome del parametro interno. È equivalente a func myFunc(name name: Int).

Se si desidera che la funzione sia richiamabile senza etichette dei parametri, utilizzare il trattino basso _per rendere l'etichetta nulla / ignorata. (In tal caso, è necessario fornire un nome interno se si desidera poter utilizzare il parametro.)

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

In una dichiarazione di assegnazione, un carattere di sottolineatura significa "non assegnare a nulla". Puoi usarlo se vuoi chiamare una funzione che restituisce un risultato ma non ti interessa il valore restituito.

_ = someFunction()

Oppure, come nell'articolo a cui ti sei collegato, per ignorare un elemento di una tupla restituita:

let (x, _) = someFunctionThatReturnsXandY()

Quando si scrive una chiusura che implementa un tipo di funzione definito, è possibile utilizzare il trattino basso per ignorare alcuni parametri.

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

Allo stesso modo, quando si dichiara una funzione che adotta un protocollo o sostituisce un metodo superclasse, è possibile utilizzare _per i nomi dei parametri per ignorare i parametri. Poiché il protocollo / superclasse potrebbe anche definire che il parametro non ha etichetta, è possibile anche finire con due trattini bassi di fila.

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

In qualche modo correlato agli ultimi due stili: quando si utilizza un costrutto di controllo del flusso che lega una variabile / costante locale, è possibile utilizzare _per ignorarlo. Ad esempio, se si desidera iterare una sequenza senza accedere ai suoi membri:

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

Se si associano i casi di tupla in un'istruzione switch, il carattere di sottolineatura può funzionare come carattere jolly, come in questo esempio (abbreviato da uno in The Swift Programming Language ):

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

Un'ultima cosa che non è del tutto legato, ma che io includo dal momento che (come notato da commenti) sembra condurre le persone qui: Una sottolineatura in un identificatore - ad esempio var _foo, func do_the_thing(), struct Stuff_- mezzi niente in particolare a Swift, ma ha alcuni usi tra i programmatori.

I caratteri di sottolineatura all'interno di un nome sono una scelta di stile, ma non sono preferiti nella comunità Swift, che ha forti convenzioni sull'uso di UpperCamelCase per i tipi e lowerCamelCase per tutti gli altri simboli.

Il prefisso o il suffisso di un nome di simbolo con trattino basso è una convenzione di stile, storicamente utilizzata per distinguere i simboli di solo uso privato / interno dall'API esportata. Tuttavia, Swift ha dei modificatori di accesso per questo, quindi questa convenzione è generalmente considerata non idiomatica in Swift.

Alcuni simboli con prefissi con doppio trattino di sottolineatura ( func __foo()) si nascondono nelle profondità degli SDK di Apple: si tratta di simboli (Obj) C importati in Swift usando l' NS_REFINED_FOR_SWIFTattributo. Apple lo usa quando vuole creare una versione "più Swifty" di un'API (Obj) C - per esempio, per trasformare un metodo indipendente dal tipo in un metodo generico . Devono utilizzare l'API importata per far funzionare la raffinata versione di Swift, quindi la usano __per tenerla disponibile nascondendola dalla maggior parte degli strumenti e della documentazione.


@rickster, Qual è il significato del trattino basso all'inizio di un metodo, come questo-> func _copyContents (inizializzazione ptr: UnsafeMutableBufferPointer <Element>) -> (Iterator, UnsafeMutableBufferPointer <Element> .Index)} dal protocollo Sequence.
dev gr

@devgr: completamente estraneo, quindi consiglierei di pubblicare una domanda separata.
rickster,

Certo, posterò una domanda separata.
dev gr

Grazie per "non assegnare a nulla" per un ritorno di funzione. Questo era quello che stavo cercando.
absin

8

Oltre alla risposta accettata, uno dei casi d'uso di _è quando è necessario scrivere un numero lungo nel codice

Numero più leggibile

Questo non è facile da leggere:

let x = 1000000000000

Puoi aggiungere _il numero per renderlo più leggibile dall'uomo:

let x = 1_000_000_000_000

6

Da Swift 3, specificare i nomi dei parametri nelle chiamate di funzione è diventato obbligatorio, anche per il primo. Pertanto, poiché ciò potrebbe causare enormi problemi al codice scritto in swift 2, è possibile utilizzare un carattere di sottolineatura nella dichiarazione per evitare di dover scrivere il nome del parametro su chiamata. Quindi, in questo caso, sta dicendo "non preoccuparti del nome del parametro esterno". Dove il nome del parametro esterno è ciò che si chiama i parametri al di fuori della funzione (su chiamata) non all'interno. Questi nomi di parametri esterni sono chiamati etichette argomento. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ... vedi come al parametro vengono assegnati due nomi? bene il primo è dove sta andando il trattino basso. Spero che questo aiuti, e chiedi se è ancora confuso.


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

Il _è un segnaposto per il nome del parametro. Nel tuo esempio, li chiami in modo diverso, nella seconda funzione, devi scrivere il nome del parametro a: 1.

La convenzione del nome della funzione di Swift è funcName(param1:param2:), e ha bisogno di _come segnaposto per creare il nome della funzione.

Nel nome, il nome è

divmod(_:_:)

Mentre il secondo è

divmod(a:b:)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.