Qual é o representante _ sublinhado no Swift References?

144

Na seção de referência dos documentos da Apple, existem muitas instâncias desse tipo de coisa:

func runAction(_action: SKAction!)

O 'Objetivo-C' equivalente 'disso é:

- (void)runAction:(SKAction *)action

Parece-me que provavelmente é importante que (na referência Swift) exista um espaço após o sublinhado e a "ação" serem escritas em itálico.

Mas não consigo descobrir o que isso está tentando transmitir. Então talvez a pergunta seja ... existe uma referência para as convenções usadas nas referências?

- aqui está a página que estou referenciando nesta referência ao uso de sublinhado: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

Atualizar

O Swift 3 fez algumas alterações na maneira como os nomes de parâmetros de função / método e os rótulos de argumentos são usados ​​e nomeados. Isso tem implicações sobre esta questão e sua resposta. O @Rickster faz um trabalho incrível ao responder a uma pergunta diferente sobre _underscores em funções que esclarece muito isso aqui: Por que preciso de sublinhados rapidamente?

Confuso
fonte
3
Marcado com [underscore.js] ??
Martin R
3
A documentação está seguindo a convenção matemática de usar itálico para nomes de variáveis. Por exemplo: sin² a + cos² a = 1.
rob mayoff

Respostas:

116

Ambas as respostas estavam corretas, mas quero esclarecer um pouco mais.

_é usado para modificar o comportamento do nome do parâmetro externo para métodos .

Na seção Nomes de Parâmetros Locais e Externos para Métodos da documentação, ele diz:

Swift fornece ao primeiro nome de parâmetro em um método um nome de parâmetro local por padrão e fornece o segundo e os nomes de parâmetro subseqüentes, tanto nomes de parâmetros locais quanto externos por padrão.

Por outro lado, funções por padrão não possuem nomes de parâmetros externos.

Por exemplo, temos este foo()método definido na classe Bar:

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

Quando você liga foo(), é chamado como bar.foo("Hello", s2: "World").

Mas , você pode substituir esse comportamento usando _na frente de s2onde ele foi declarado.

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

Então, quando você chama foo, pode ser chamado simplesmente como bar.foo("Hello", "World")sem o nome do segundo parâmetro.

De volta ao seu caso, runActioné um método porque está associado ao tipo SKNode, obviamente. Assim, colocar um _parâmetro before actionpermite que você chame runActionsem um nome externo.

Atualização para Swift 2.0

Função e método agora funcionam da mesma maneira em termos de declaração de nome de argumento local e externo.

As funções agora são chamadas usando o nome do parâmetro externo por padrão, iniciando no segundo parâmetro. Esta regra se aplica apenas ao código Swift puro.

Portanto, fornecendo um _na frente de uma função , o chamador não precisará especificar o nome do parâmetro externo, exatamente como o que você faria para um método .

Aaron He
fonte
9
Confuso, se a _gravação antes do segundo parâmetro, sua resposta é clara o suficiente; what if in func runAction(_action: SKAction!), the _é antes do primeiro parâmetro ou se você escrever o código a seguir, o func foo(_ s1: String) { // your code }Xcode forneceria um aviso, mas há muitos códigos como func bringSubviewToFront(_ view: UIView)na referência, por que?
Will Zhang
10
então, basicamente, faz isso sem motivo e confunde todo mundo. impressionante.
Botbot 4/04/14
2
Um sublinhado é conhecido como desenvolvedor
user2143356
@ Wyatt Zhang, diz o documento, que o uso do _primeiro parâmetro é estranho. Posso supor que os designers pensam que obviamente é suficiente para o seu código e não melhora a legibilidade, pelo contrário, suja o código. Então você recebe o aviso. A referência tem o objetivo oposto: deve ser o mais claro possível - portanto, o sublinhado do primeiro parâmetro é mencionado para TODOS os métodos. Isso explicaria tudo)
Dmitry Gryazin
4
É importante notar que o Swift 3.0 muda as coisas. Todos os rótulos são obrigatórios, a menos que você especifique o contrário. Portanto, o -antes do primeiro parâmetro não é mais estranho. Por exemplo: override func viewWillAppear(_ animated: Bool)sinais de que o chamador (código Objective-C) não estará usando um rótulo de parâmetro
Sr. T
85

O sublinhado é um token geral usado para indicar um valor descartado.

Nesse caso específico, significa que a função será chamada como em runAction(argument)vez derunAction(action:argument)

Em outros contextos, tem outro significado semelhante, por exemplo:

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

Isso significa que queremos apenas executar o bloco 5 vezes e não nos importamos com o índice dentro do bloco.

Neste contexto:

let (result, _) = someFunctionThatReturnsATuple()

Isso significa que não nos importamos com o que é o segundo elemento da tupla, apenas o primeiro.

David Berry
fonte
Então, neste caso, o argumento (uma ação) é uma opção?
Confuso
1
Não, faz com que o nome do parâmetro externo (ação :) neste caso fique vazio, sendo omitido. O argumento ainda é necessário, mas não está marcado com action :.
David Berry
4
A resposta real é uma combinação da resposta do @ dasblinkenlight e da minha. Ele aborda esse caso específico com mais precisão, enquanto o meu aborda a questão mais ampla, o que significa?
David Berry
4
Você também pode usar o sinal de descarte para números muito grandes, para torná-los mais legíveis assimlet pi = 3.141_592_653_59
SMP
divertidamente, você também pode usá-lo para fazer muito grandes números menos legível, comolet pi = 3.1_4_15_92___63
David Berry
15

Desde o Swift 3, todos os rótulos de argumentos são obrigatórios por padrão .

Você pode forçar um IDE a ocultar um rótulo de argumento _.

func foo(a: String) {
}

func foo2(_ a: String) {
}

chamado foo(a: "abc")efoo2("abc")

Nota: Isso pode ser usado apenas quando aé o rótulo do argumento (externo) e o nome da variável (interna) ao mesmo tempo. É equivalente - func foo(a a: String)não aceita o _.

Por que a Apple está usando?

Você pode ver que a Apple está usando-o na API. As bibliotecas da Apple ainda são escritas em Objective-C (caso contrário, elas compartilham os mesmos nomes de função, que foram projetados para a sintaxe Objective-C)

Funções como applicationWillResignActive(_ application: UIApplication)teriam um nome de parâmetro redundanteapplication , pois já existe o aplicativo em seu nome de função.

Seu exemplo

func runAction(_ action: SKAction!)seria chamado sem sua _marca como runAction(action:). O nome do parâmetro actionseria redundante, pois já existe um no nome da função. Esse é o propósito e por que está lá.

Jakub Truhlář
fonte
13

Um identificador na frente da declaração de parâmetro define um nome de parâmetro externo . Este é o nome que deve ser fornecido pelo chamador ao chamar a função:

func someFunction(externalParameterName localParameterName: Int)

Swift fornece um nome externo automático para qualquer parâmetro padrão definido, se você não fornecer um nome externo. O uso de um sublinhado para o nome do parâmetro externo opta por esse comportamento:

Você pode desativar esse comportamento escrevendo um sublinhado ( _) em vez de um nome externo explícito ao definir o parâmetro.

Você pode ler mais sobre esse comportamento na seção Nomes externos para parâmetros com valores padrão aqui .

dasblinkenlight
fonte
então ... deixe-me ver se minha tolice está certa. Neste exemplo, devo nomear meu parâmetro variável / constante como "ação" e atribuí-lo ao SKAction que desejo executar por essa função, e Swift nomeia automaticamente o parâmetro padrão necessário "ação". NO ENTANTO, se eu quiser nomear essa ação de forma personalizada, devo usar o sublinhado na chamada da função?
Confuso
4
@Confused Meu entendimento é que SKos designers não querem que você escreva actionduas vezes, porque "action" já faz parte do nome da função. Em outras palavras, eles não querem que você escreva sprite.runAction(action:moveGroundSpritesForever). O objetivo dos nomes de parâmetros externos era tornar seu código "lido como uma frase"; o uso actionduas vezes derrotaria o objetivo disso.
dasblinkenlight
Algumas luzes se acenderam na escuridão. Eu acho que entendi. Esse recurso do idioma destina-se a fazer com que as funções de chamada no Swift se pareçam com a maneira como você chamaria um método com parâmetros no Objective-C. Talvez.
Confuso
1
No entanto, o sublinhado pode ser usado para, de alguma forma, optar por não ter esses nomes de parâmetros externos para parâmetros definidos com um valor padrão ... apenas ainda não vi como isso é feito. Vai continuar procurando.
Confuso
Então ... em resumo, ele simplesmente alterna entre parâmetros nomeados e parâmetros ordinais, para que você possa alternar facilmente entre foo.bar(param: 'fiddle') e foo.bar('fiddle') NOTA: com apenas um argumento, ele realmente não se torna aparente ... mas com vários argumentos, torna-se muito relevante: foo.bar(param1: 'fiddle', param2: 'dee') vs foo.bar('fiddle','dee')
jrypkahauer
10

Eu acho que isso força uma convenção em Swift que a torna mais próxima do objetivo-c, que combina melhor com as convenções de cacau. Em objc, você não (externamente) nomeia seu primeiro parâmetro. Em vez disso, por convenção, você geralmente inclui o nome externo na última parte do nome do método, assim:

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

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

Para tornar as chamadas api do Swift consistentes com objc, você deseja suprimir o nome do parâmetro externo do primeiro parâmetro.

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

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")
smileBot
fonte
2
Eu gosto dessa explicação. depois de aprender o Obj-C primeiro, você esclareceu as coisas. Ele também destaca a importância de nomear o método adequadamente em Swift, ou seja, a última parte do nome do método deve descrever o primeiro argumento, como é normalmente o caso em Obj-C. coisa boa.
Rrrrrraul
5

Na verdade, há uma diferença entre o código real usado para definir um método e a declaração do método nos documentos da Apple. Vamos dar UIControl 's - addTarget: ação: forControlEvents: método, por exemplo, o código real é: insira a descrição da imagem aqui

Mas, nos documentos, ele aparece assim (observe _ antes do destino): insira a descrição da imagem aqui

No código real, _ é usado para fazer com que o nome externo do segundo parâmetro ou subseqüente não apareça quando um método é chamado, enquanto nos documentos, _ antes do nome local de um parâmetro indica que, quando você chama um método ou uma função, não deve fornecer um nome externo.

Não há nome externo quando uma função é chamada por padrão, a menos que você forneça seu próprio nome ou adicione # antes (sem espaço em branco) do nome local de um parâmetro, por exemplo, é assim que usamos o dispatch_after : insira a descrição da imagem aqui

E nos documentos, aparece assim (observe três _): insira a descrição da imagem aqui

A convenção da declaração da função é exatamente a mesma que descrevi para o método.

fujianjin6471
fonte
1

Apenas mais visualmente.

insira a descrição da imagem aqui

Como você pode ver, _basta fazer omitir um nome de parâmetro local ou não.

Nik Kov
fonte