Swift-style-guide: Funções vs. Métodos

Criado em 6 jul. 2015  ·  26Comentários  ·  Fonte: raywenderlich/swift-style-guide

O guia deve ser explícito sobre o uso apropriado da função e do método ao escrever. Tendo dado uma olhada nos documentos da linguagem de programação Swift da Apple, algo como:

Um método é uma função associada a uma classe, estrutura ou enum. Isso vale para métodos de instância e tipo. Uma função, por outro lado, é declarada no âmbito global e não pertence a nenhum tipo.

seria suficiente.

Comentários muito úteis

Que tal algo como isso:

Métodos vs Funções Livres

Métodos são funções associadas a um tipo e preferenciais devido à sua capacidade de descoberta de preenchimento automático. Funções livres são menos comuns, mas fazem sentido quando uma operação não está intimamente associada a um determinado tipo ou instância.

Preferido

let sorted = items.mergeSort()  // easily discoverable
rocket.launch()  // a mutating method

Não preferido

let sorted = mergeSort(items)
launch(&rocket)

Exceções de função grátis

let tuples = zip(a, b)  // feels natural as a free function (symmetry)
let value = max(x,y,z)  // another free function that feels natural

Todos 26 comentários

Também vi funções chamadas de "funções livres". Presumo que "grátis" significa "não associado a nenhum objeto".

As funções têm mais opções de escopo do que tipo e global, em Swift.

Eu apenas assumi que os métodos normais em Objective-C agora eram chamados de functiona em Swift . Todo o material que li em termos de fóruns, blogs, tutoriais, etc. refere-se a eles simplesmente como functions , mesmo quando pertencem a uma classe ou enum.

@mitchellporter Os próprios documentos da Apple são claros sobre quando algo deve ser referido como uma função ou método, conforme a citação acima.

Os tutoriais em raywenderlich.com também seguem as diretrizes da Apple aqui, e é por isso que devem ser incluídos no guia de estilo.

Existem funções e métodos em Objective-C também; nem tudo é um método. 😉

@micpringle Faz sentido, mas juro que li muito material onde eles simplesmente chamam de function mesmo quando pertence a uma classe. Acho que não sou o único que está sempre usando function também, será interessante ver se isso muda no futuro.

As "funções" dentro dos métodos são "métodos aninhados"?
O que são funções dentro de encerramentos ou outras funções não chamadas?

struct Struct {
   let closure = {
      func whoAmI() {}
   }

   var any: Any? {
      func jeanValjean() {}
      return nil
   }
}

Acho que seriam classificadas como funções anônimas (IMO), já que, tecnicamente, elas não "pertencem" a nada e só existem nesse escopo específico e não podem ser acessadas de fora dele.

Não acho que "função anônima" seja o nome certo aqui - isso geralmente se refere a encerramentos.

Eu as chamaria de "funções aninhadas": "funções" porque são funções, não métodos anexados a um tipo ou instância nomeada. E "aninhados" porque ... eles estão aninhados! Talvez "funções com escopo", mas isso não parece tão claro.

Desculpe, não sabia que encerramentos também eram chamados de funções anônimas. :]

Funções aninhadas soam bem para mim. Eu concordo que o escopo não parece certo.

Acho que "funções aninhadas" dentro de qualquer coisa, seja um método ou não, parece claro o suficiente para o futuro previsível.

E embora eu ache que funções aninhadas com nomes as tornem "nônimas", não estou certo sobre o que exatamente é "anônimo", no entanto, quando se trata de encerramentos, especialmente os armazenados e imutáveis, que são muito parecidos com funções. Estou inclinado a acreditar que a função armazenada é realmente anônima, mas o fechamento que a captura, e potencialmente algum estado, é o que tem o nome. É assim que é ensinado para C #, onde a sintaxe lambda é uma abreviação para construir o que chama de Delegate.
https://msdn.microsoft.com/en-us/library/system.delegate (v = vs.110) .aspx

func nonymous() {
   func nonymous() {}
}

let anonymouses: [() -> ()] = [].map
{$0} // This "transform" is also anonymous.

let unlcearToMeWhetherNonymous = {}

É um ponto sutil e possivelmente até discutível quando você chega às entranhas de Swift e tudo é o mesmo, mas declarar algo com func definitivamente dá um nome à coisa. Em contraste, um encerramento é apenas um bloco de código sem nome. Você poderia atribuí-lo a uma variável ou constante, é claro, mas isso é apenas armazenar um ponteiro para a coisa.

Novamente, é uma diferença meio artificial. Você poderia ser todo tipo lisp e dizer que func é apenas um açúcar sintático para dar um nome a um encerramento.

Que tal algo como isso:

Métodos vs Funções Livres

Métodos são funções associadas a um tipo e preferenciais devido à sua capacidade de descoberta de preenchimento automático. Funções livres são menos comuns, mas fazem sentido quando uma operação não está intimamente associada a um determinado tipo ou instância.

Preferido

let sorted = items.mergeSort()  // easily discoverable
rocket.launch()  // a mutating method

Não preferido

let sorted = mergeSort(items)
launch(&rocket)

Exceções de função grátis

let tuples = zip(a, b)  // feels natural as a free function (symmetry)
let value = max(x,y,z)  // another free function that feels natural

A respeito de,

Exceções de função grátis

let tuples = zip(a, b)  // feels natural as a free function (symmetry)
let value = max(x,y,z)  // another free function that feels natural

"Parece natural" é bastante ambíguo e subjetivo.

Podemos esclarecer o que queremos dizer aqui?

Além disso, tanto zip quanto max também sofreriam do problema de // hard to discover que você mencionou no PR.

IMHO, acho que zip é um exemplo estranho. Problemas que eu tenho com isso:

  • O que realmente está _fazendo_? Combinando a e b ? Comprimir a e b alguma forma? Algo mais? Sem mais contexto, é difícil saber.

Em vez de

Funções livres são menos comuns, mas fazem sentido quando uma operação não está intimamente associada a um determinado tipo ou instância.

Que tal agora?

Funções livres, que não estão anexadas a uma classe ou tipo, devem ser usadas com moderação. Quando possível, prefira usar um método em vez de uma função livre. Isso ajuda na legibilidade e descoberta.

As funções livres são mais apropriadas quando não estão associadas a nenhum tipo ou instância particular.

Estou reabrindo este problema para buscar uma discussão mais aprofundada sobre Free Function Exceptions .

Bem, esta é uma função de biblioteca padrão. Tem precedência em linguagens como R, Python, C #, C ++. (Via boost).

Bem, esta é uma função de biblioteca padrão.

Sério? Não usei no iOS ... * envergonhado *

Vou dar uma olhada ... Se for amplamente compreendido / usado no iOS, talvez minha preocupação aqui esteja errada ...

Eu gosto da sua sugestão de verborragia ... Estou relutante em desistir do exemplo zip. (PS: A equipe RW Swift tem um estatuto maior (ou menor) do que o iOS.)

A equipe RW Swift tem um estatuto maior (ou menor) do que o iOS.

👍 Verdadeiro. ;]

Depois de revisar o que o zip faz , devo deixá-lo como um exemplo. 👍

Peço desculpas pela minha experiência do momento de novato rápido aqui. 😉

Sem problemas. Obrigado pela sua ajuda como sempre. BTW, acabei de notar que você não é mencionado nos créditos. Eu vou consertar isso também.

Não tenho certeza se as funções livres são sempre a melhor solução. Se forem usados, acho que devem adicionar funcionalidade que não foi abordada em outro lugar.

max

let max = Swift.max(0, 1, 2)
let maxElement = [0, 1, 2].maxElement()!

maxElement deveria ser uma propriedade e não um método, mas ainda acho que a função livre é redundante. Se eles não compilarem para a mesma coisa, então acho que o compilador deve ser melhorado, mas mesmo que não seja, não acho que o desempenho importará; Não acho que as pessoas usariam a função max com muitos elementos.

fecho eclair
Em C #, zip é implementado como o equivalente a um método de extensão de protocolo Swift . Não acho que seja melhor, mas é um exemplo de como lidar com zip diferente.

Em Swift, zip é a mesma coisa que este inicializador para Zip2Sequence . Seria bom ter uma maneira de representar uma sequência compactada de um número variável de sequências de entrada, mas até que isso aconteça, acho que usar o inicializador diretamente está bom.

zip([1...3], ["a"..."c"])
Zip2Sequence([1...3], ["a"..."c"])

operadores
A grande maioria das funções gratuitas que escrevi em Swift são operadores. Já vi Chris Lattner e Joe Groff sugerindo que os operadores poderão ser definidos dentro de tipos, à la C #, no futuro, portanto, os operadores também podem seguir quaisquer convenções escolhidas para outras funções. Sua implementação atual como função livre apenas provavelmente não deve ser usada como uma diretriz.

operadores
A grande maioria das funções gratuitas que escrevi em Swift são operadores. Eu vi Chris Lattner e Joe Groff sugerindo que os operadores poderão ser definidos dentro de tipos, à la C #, no futuro ...

Sim, esta é provavelmente a direção que o Swift se moverá no futuro. Aqui está uma proposta bastante recente de Chris Lattner, como você mencionou.

Isso é especialmente peculiar com protocolos como Equatable , que de acordo com nossas diretrizes de extensão, essencialmente _requerem_ que você crie uma extensão vazia. Isso é estranho na melhor das hipóteses. 😞

Eu definitivamente concordo que os operadores não devem ser usados ​​como um exemplo para funções livres ideais.

Obrigado pelos comentários @ Jessy-!

Algumas notas:

Acho que maxElement() é declarado um método porque não é O (1), o que pode ser surpreendente para alguns usuários. Se você implementar uma propriedade que não seja O (1), ela precisa ser claramente documentada. (Nos tutoriais RW, temos o luxo de que todo o código esteja aberto, então não precisamos nos preocupar tanto com isso ou aplicá-lo como uma diretriz de estilo.)

Por outro lado, algumas formas de max<T: Comparable> são O (1) e tem o potencial de ser especializado para tirar vantagem do hardware. (Suponho que seja por isso que há uma versão de dois parâmetros além da versão variável, embora eu não tenha confirmado isso.)

Em qualquer caso, acho que estamos todos de acordo que as funções livres devem ser usadas com moderação, mas eu contra-atacaria _nunca_. Os exemplos usados ​​vêm da biblioteca padrão. Não vi nenhuma proposta para remover a função zip da biblioteca padrão. Há objeções às especificações da reformulação do @ JRG-Developer ou ao módulo de solicitação de pull atualmente mesclado com esta reformulação?

Sinta-se à vontade para reabrir se achar que há algo mais que precisa ser discutido. (Mesclado com a ramificação de atualização).

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

jrturton picture jrturton  ·  3Comentários

fabienwarniez picture fabienwarniez  ·  9Comentários

gokselkoksal picture gokselkoksal  ·  9Comentários

designatednerd picture designatednerd  ·  22Comentários

WingYn picture WingYn  ·  15Comentários