Skip to main content

Funções

Defina e chame funções, rotule seus argumentos e use seus valores de retorno.

Funções são pedaços de código autocontidos que realizam uma tarefa específica. Você atribui um nome a uma função que identifica o que ela faz, e esse nome é usado para "chamar" a função e realizar sua tarefa quando necessário.

A sintaxe unificada de funções do Swift é flexível o suficiente para expressar desde uma função simples no estilo C, sem nomes de parâmetros, até um método complexo no estilo Objective-C, com nomes e rótulos de argumentos para cada parâmetro. Os parâmetros podem fornecer valores padrão para simplificar as chamadas de função e podem ser passados como parâmetros in-out, modificando uma variável passada uma vez que a função tenha concluído sua execução.

Cada função no Swift tem um tipo, composto pelos tipos de parâmetros da função e pelo tipo de retorno. Você pode usar esse tipo como qualquer outro tipo no Swift, o que facilita passar funções como parâmetros para outras funções e retornar funções de funções. As funções também podem ser escritas dentro de outras funções para encapsular funcionalidades úteis dentro de um escopo de função aninhado.

Definindo e Chamando Funções

Ao definir uma função, você pode opcionalmente definir um ou mais valores nomeados e tipados que a função recebe como entrada, conhecidos como parâmetros. Você também pode opcionalmente definir um tipo de valor que a função retornará como saída quando estiver concluída, conhecido como seu tipo de retorno.

Cada função possui um nome, que descreve a tarefa que a função executa. Para usar uma função, você "chama" essa função pelo seu nome e passa valores de entrada (conhecidos como argumentos) que correspondem aos tipos dos parâmetros da função. Os argumentos de uma função sempre devem ser fornecidos na mesma ordem que a lista de parâmetros da função.

A função no exemplo abaixo é chamada de saudar(pessoa:), porque é isso que ela faz - ela recebe o nome de uma pessoa como entrada e retorna uma saudação para essa pessoa. Para realizar isso, você define um parâmetro de entrada - um valor String chamado pessoa - e um tipo de retorno String, que conterá uma saudação para essa pessoa:

func saudar(pessoa: String) -> String {
let saudacao = "Olá, " + pessoa + "!"
return saudacao
}

Toda essa informação está consolidada na definição da função, que é prefixada com a palavra-chave func. Você indica o tipo de retorno da função com a seta de retorno -> (um hífen seguido por um sinal de maior), seguido pelo nome do tipo a ser retornado.

A definição descreve o que a função faz, o que ela espera receber e o que ela retorna quando conclui sua execução. A definição facilita a chamada da função de forma inequívoca de outras partes do seu código:

print(saudar(pessoa: "Anna"))
// Imprime "Olá, Anna!"
print(saudar(pessoa: "Brian"))
// Imprime "Olá, Brian!"

Você chama a função saudar(pessoa:) passando a ela um valor de String após o rótulo do argumento pessoa, como saudar(pessoa: "Anna"). Como a função retorna um valor de String, saudar(pessoa:) pode ser envolvida em uma chamada à função print(_:separator:terminator:) para imprimir essa string e ver seu valor de retorno, como mostrado acima.

Nota

A função print(_:separator:terminator:) não possui um rótulo para seu primeiro argumento, e seus outros argumentos são opcionais, pois têm um valor padrão. Essas variações na sintaxe de função são discutidas abaixo em Rótulos de Argumentos de Função e Nomes de Parâmetros e Valores de Parâmetro Padrão.

O corpo da função saudar(pessoa:) começa definindo uma nova constante do tipo String chamada saudacao e atribuindo a ela uma mensagem simples de saudação. Em seguida, essa saudação é passada para fora da função usando a palavra-chave return. Na linha de código que contém return saudacao, a função conclui sua execução e retorna o valor atual de saudacao.

Você pode chamar a função saudar(pessoa:) várias vezes com valores de entrada diferentes. O exemplo acima mostra o que acontece quando é chamada com um valor de entrada "Anna" e um valor de entrada "Brian". A função retorna uma saudação personalizada em cada caso.

Para tornar o corpo desta função mais curto, é possível combinar a criação da mensagem e a declaração de retorno em uma única linha:

func saudarNovamente(pessoa: String) -> String {
return "Olá novamente, " + pessoa + "!"
}
print(saudarNovamente(pessoa: "Anna"))
// Imprime "Olá novamente, Anna!"

Parâmetros e Valores de Retorno de Função

Os parâmetros e valores de retorno de função são extremamente flexíveis em Swift. Você pode definir desde uma função de utilidade simples com um único parâmetro sem nome até uma função complexa com nomes expressivos para os parâmetros e diferentes opções de parâmetro.

Funções Sem Parâmetros

As funções não são obrigadas a definir parâmetros de entrada. Aqui está uma função sem parâmetros de entrada, que sempre retorna a mesma mensagem de String sempre que é chamada:

func digaOlaMundo() -> String {
return "olá, mundo"
}
print(digaOlaMundo())
// Imprime "olá, mundo"

A definição da função ainda precisa de parênteses após o nome da função, mesmo que ela não receba nenhum parâmetro. O nome da função também é seguido por um par de parênteses vazios quando a função é chamada.

Funções com Múltiplos Parâmetros

As funções podem ter múltiplos parâmetros de entrada, os quais são escritos dentro dos parênteses da função, separados por vírgulas.

Esta função recebe o nome de uma pessoa e se ela já foi cumprimentada como entrada e retorna uma saudação apropriada para essa pessoa:

func saudar(pessoa: String, jaCumprimentada: Bool) -> String {
if jaCumprimentada {
return saudarNovamente(pessoa: pessoa)
} else {
return saudar(pessoa: pessoa)
}
}

print(saudar(pessoa: "Tim", jaCumprimentada: true))
// Imprime "Olá novamente, Tim!"

Você chama a função saudar(pessoa:jaCumprimentada:) passando a ela tanto um valor de argumento String rotulado como pessoa quanto um valor de argumento Bool rotulado como jaCumprimentada entre parênteses, separados por vírgulas. Observe que esta função é distinta da função saudar(pessoa:) mostrada em uma seção anterior. Embora ambas as funções tenham nomes que começam com saudar, a função saudar(pessoa:jaCumprimentada:) recebe dois argumentos, enquanto a função saudar(pessoa:) recebe apenas um.

Funções Sem Valores de Retorno

Não é necessário que as funções definam um tipo de retorno. Aqui está uma versão da função saudar(pessoa:), que imprime seu próprio valor de String em vez de retorná-lo:

func saudar(pessoa: String) {
print("Olá, \(pessoa)!")
}
saudar(pessoa: "Dave")
// Imprime "Olá, Dave!"

Porque não precisa retornar um valor, a definição da função não inclui a seta de retorno (->) nem um tipo de retorno.

Nota

Estritamente falando, esta versão da função saudar(pessoa:) ainda retorna um valor, mesmo que nenhum valor de retorno seja definido. Funções sem um tipo de retorno definido retornam um valor especial do tipo Void. Isso é simplesmente uma tupla vazia, escrita como ().

O valor de retorno de uma função pode ser ignorado quando ela é chamada:

func imprimirEContar(string: String) -> Int {
print(string)
return string.count
}

func imprimirSemContar(string: String) {
let _ = imprimirEContar(string: string)
}

imprimirEContar(string: "Olá, mundo")
// imprime "Olá, mundo" e retorna um valor de 12

imprimirSemContar(string: "Olá, mundo")
// imprime "Olá, mundo" mas não retorna um valor

A primeira função, imprimirEContar(string:), imprime uma string e, em seguida, retorna a contagem de caracteres dela como um Int. A segunda função, imprimirSemContar(string:), chama a primeira função, mas ignora o valor retornado. Quando a segunda função é chamada, a mensagem ainda é impressa pela primeira função, mas o valor retornado não é utilizado.

Nota

Valores de retorno podem ser ignorados, mas uma função que indica que retornará um valor deve sempre fazê-lo. Uma função com um tipo de retorno definido não pode permitir que o controle saia do final da função sem retornar um valor, e tentar fazê-lo resultará em um erro de compilação.

Funções com Múltiplos Valores de Retorno

Você pode usar um tipo de tupla como o tipo de retorno para uma função para retornar múltiplos valores como parte de um valor de retorno composto.

O exemplo abaixo define uma função chamada minMax(array:), que encontra os números menor e maior em um array de valores Int:

func minMax(array: [Int]) -> (min: Int, max: Int) {
var atualMin = array[0]
var atualMax = array[0]
for valor in array[1..<array.count] {
if valor < atualMin {
atualMin = valor
} else if valor > atualMax {
atualMax = valor
}
}
return (atualMin, atualMax)
}

A função minMax(array:) retorna uma tupla contendo dois valores Int. Esses valores são rotulados como min e max para que possam ser acessados pelo nome ao consultar o valor de retorno da função.

O corpo da função minMax(array:) começa definindo duas variáveis de trabalho chamadas atualMin e atualMax com o valor do primeiro inteiro no array. A função então itera sobre os valores restantes no array e verifica cada valor para ver se é menor ou maior do que os valores de atualMin e atualMax, respectivamente. Por fim, os valores mínimos e máximos globais são retornados como uma tupla de dois valores Int.

Como os valores dos membros da tupla são nomeados como parte do tipo de retorno da função, eles podem ser acessados com a sintaxe de ponto para recuperar os valores mínimos e máximos encontrados:

let limites = minMax(array: [8, -6, 2, 109, 3, 71])
print("O mínimo é \(limites.min) e o máximo é \(limites.max)")
// Imprime "O mínimo é -6 e o máximo é 109"

Observe que os membros da tupla não precisam ser nomeados no momento em que a tupla é retornada da função, pois seus nomes já estão especificados como parte do tipo de retorno da função.

Funções com Retorno Implícito

Se todo o corpo da função for uma única expressão, a função retorna implicitamente essa expressão. Por exemplo, ambas as funções abaixo têm o mesmo comportamento:

func saudacao(para pessoa: String) -> String {
"Olá, " + pessoa + "!"
}
print(saudacao(para: "Dave"))
// Imprime "Olá, Dave!"

func outraSaudacao(para pessoa: String) -> String {
return "Olá, " + pessoa + "!"
}
print(outraSaudacao(para: "Dave"))
// Imprime "Olá, Dave!"

A definição completa da função saudacao(para:) é a mensagem de saudação que ela retorna, o que significa que pode usar esta forma mais curta. A função outraSaudacao(para:) retorna a mesma mensagem de saudação, utilizando a palavra-chave return como em uma função mais longa. Qualquer função que você escreva com apenas uma linha de retorno pode omitir o return.

Como você verá na Declaração de Getter Abreviada, os getters de propriedades também podem usar um retorno implícito.

Nota

O código que você escreve como um valor de retorno implícito precisa retornar algum valor. Por exemplo, você não pode usar print(13) como um valor de retorno implícito. No entanto, você pode usar uma função que nunca retorna, como fatalError("Oh no!"), como um valor de retorno implícito, porque o Swift sabe que o retorno implícito não ocorre.

Rótulos de Argumentos de Função e Nomes de Parâmetros

Cada parâmetro de função possui tanto um rótulo de argumento quanto um nome de parâmetro. O rótulo de argumento é usado ao chamar a função; cada argumento é escrito na chamada da função com seu rótulo de argumento antes dele. O nome do parâmetro é usado na implementação da função. Por padrão, os parâmetros usam seu nome de parâmetro como seu rótulo de argumento.

func algumaFuncao(primeiroNomeDoParametro: Int, segundoNomeDoParametro: Int) {
// No corpo da função, primeiroNomeDoParametro e segundoNomeDoParametro
// referem-se aos valores dos argumentos para o primeiro e segundo parâmetros.
}
algumaFuncao(primeiroNomeDoParametro: 1, segundoNomeDoParametro: 2)

Todos os parâmetros devem ter nomes únicos. Embora seja possível para vários parâmetros terem o mesmo rótulo de argumento, rótulos de argumento únicos ajudam a tornar seu código mais legível.

Especificando Rótulos de Argumento

Você escreve um rótulo de argumento antes do nome do parâmetro, separado por um espaço:

func algumaFuncao(rotuloDeArgumento nomeDoParametro: Int) {
// No corpo da função, nomeDoParametro se refere ao valor do argumento
// para esse parâmetro.
}

Aqui está uma variação da função saudar(pessoa:) que recebe o nome e a cidade natal de uma pessoa e retorna uma saudação:

func saudar(pessoa: String, de cidadeNatal: String) -> String {
return "Olá \(pessoa)! Que bom que você pode visitar de \(cidadeNatal)."
}
print(saudar(pessoa: "Bill", de: "Cupertino"))
// Imprime "Olá Bill! Que bom que você pode visitar de Cupertino."

O uso de rótulos de argumento pode permitir que uma função seja chamada de maneira expressiva, semelhante a uma frase, ao mesmo tempo em que fornece um corpo de função que é legível e claro em sua intenção.

Omitindo Rótulos de Argumento

Se você não quiser um rótulo de argumento para um parâmetro, escreva um sublinhado (_) em vez de um rótulo de argumento explícito para esse parâmetro.

func algumaFuncao(_ primeiroNomeDoParametro: Int, segundoNomeDoParametro: Int) {
// No corpo da função, primeiroNomeDoParametro e segundoNomeDoParametro
// referem-se aos valores de argumento para o primeiro e segundo parâmetros.
}
algumaFuncao(1, segundoNomeDoParametro: 2)

Se um parâmetro tiver um rótulo de argumento, o argumento deve ser rotulado quando você chama a função.

Valores de Parâmetro Padrão

Você pode definir um valor padrão para qualquer parâmetro em uma função atribuindo um valor ao parâmetro após o tipo desse parâmetro. Se um valor padrão for definido, você pode omitir esse parâmetro ao chamar a função.

func algumaFuncao(parametroSemPadrao: Int, parametroComPadrao: Int = 12) {
// Se você omitir o segundo argumento ao chamar esta função, então
// o valor de parametroComPadrao é 12 dentro do corpo da função.
}
algumaFuncao(parametroSemPadrao: 3, parametroComPadrao: 6) // parametroComPadrao é 6
algumaFuncao(parametroSemPadrao: 4) // parametroComPadrao é 12

Coloque os parâmetros que não têm valores padrão no início da lista de parâmetros de uma função, antes dos parâmetros que têm valores padrão. Parâmetros que não têm valores padrão geralmente são mais importantes para o significado da função - escrevê-los primeiro torna mais fácil reconhecer que a mesma função está sendo chamada, independentemente de quaisquer parâmetros padrão serem omitidos.

Parâmetros Variádicos

Um parâmetro variádico aceita zero ou mais valores de um tipo especificado. Você utiliza um parâmetro variádico para especificar que o parâmetro pode receber um número variável de valores de entrada quando a função é chamada. Escreva parâmetros variádicos inserindo três pontos (...) após o nome do tipo do parâmetro.

Os valores passados a um parâmetro variádico são disponibilizados dentro do corpo da função como um array do tipo apropriado. Por exemplo, um parâmetro variádico com o nome de numeros e tipo Double... fica disponível dentro do corpo da função como um array constante chamado numeros do tipo [Double].

O exemplo abaixo calcula a média aritmética (também conhecida como média) para uma lista de números de qualquer comprimento:

func mediaAritmetica(_ numeros: Double...) -> Double {
var total: Double = 0
for numero in numeros {
total += numero
}
return total / Double(numeros.count)
}
mediaAritmetica(1, 2, 3, 4, 5)
// retorna 3.0, que é a média aritmética desses cinco números
mediaAritmetica(3, 8.25, 18.75)
// retorna 10.0, que é a média aritmética desses três números

Uma função pode ter múltiplos parâmetros variádicos. O primeiro parâmetro que vem após um parâmetro variádico deve ter um rótulo de argumento. O rótulo de argumento torna inequívoco quais argumentos são passados para o parâmetro variádico e quais argumentos são passados para os parâmetros que vêm após o parâmetro variádico.

Parâmetros de Entrada-Saída

Os parâmetros de função são constantes por padrão. Tentar alterar o valor de um parâmetro de função de dentro do corpo dessa função resulta em um erro de tempo de compilação. Isso significa que você não pode alterar o valor de um parâmetro por engano. Se você deseja que uma função modifique o valor de um parâmetro e que essas alterações persistam após o término da chamada da função, defina esse parâmetro como um parâmetro de entrada-saída.

Você escreve um parâmetro de entrada-saída colocando a palavra-chave inout imediatamente antes do tipo do parâmetro. Um parâmetro de entrada-saída tem um valor que é passado para a função, é modificado pela função e é passado de volta para fora da função para substituir o valor original. Para uma discussão detalhada sobre o comportamento dos parâmetros de entrada-saída e otimizações do compilador associadas, consulte Parâmetros de Entrada-Saída.

Você só pode passar uma variável como argumento para um parâmetro de entrada-saída. Você não pode passar uma constante ou um valor literal como argumento, porque constantes e literais não podem ser modificados. Você coloca um e comercial (&) diretamente antes do nome da variável ao passá-la como argumento para um parâmetro de entrada-saída, para indicar que ela pode ser modificada pela função.

Nota

Parâmetros de entrada-saída não podem ter valores padrão, e parâmetros variádicos não podem ser marcados como inout.

Aqui está um exemplo de uma função chamada trocarDoisInteiros(::), que tem dois parâmetros inteiros in-out chamados a e b:

func trocarDoisInteiros(_ a: inout Int, _ b: inout Int) {
let temporarioA = a
a = b
b = temporarioA
}

A função trocarDoisInteiros(_:_:) simplesmente troca o valor de b para a, e o valor de a para b. A função realiza essa troca armazenando o valor de a em uma constante temporária chamada temporarioA, atribuindo o valor de b a a, e então atribuindo temporarioA a b.

Você pode chamar a função trocarDoisInteiros(_:_:) com duas variáveis do tipo Int para trocar seus valores. Note que os nomes algumInt e outroInt são prefixados com um e comercial quando são passados para a função trocarDoisInteiros(_:_:):

var algumInt = 3
var outroInt = 107
trocarDoisInteiros(&algumInt, &outroInt)
print("algumInt agora é \(algumInt), e outroInt agora é \(outroInt)")
// Imprime "algumInt agora é 107, e outroInt agora é 3"

O exemplo acima mostra que os valores originais de algumInt e outroInt são modificados pela função trocarDoisInteiros(::), mesmo que tenham sido originalmente definidos fora da função.

Nota

Parâmetros de entrada e saída não são o mesmo que retornar um valor de uma função. O exemplo trocarDoisInteiros acima não define um tipo de retorno nem retorna um valor, mas ainda assim modifica os valores de algumInt e outroInt. Parâmetros de entrada e saída são uma forma alternativa para uma função ter um efeito fora do escopo do corpo da função.

Tipos de Função

Cada função possui um tipo de função específico, composto pelos tipos de parâmetros e pelo tipo de retorno da função.

Por exemplo:

func somarDoisInteiros(_ a: Int, _ b: Int) -> Int {
return a + b
}

func multiplicarDoisInteiros(_ a: Int, _ b: Int) -> Int {
return a * b
}

Este exemplo define duas funções matemáticas simples chamadas somarDoisInteiros e multiplicarDoisInteiros. Essas funções recebem cada uma dois valores Int e retornam um valor Int, que é o resultado de realizar uma operação matemática apropriada.

O tipo de ambas essas funções é (Int, Int) -> Int. Isso pode ser lido como:

"Uma função que tem dois parâmetros, ambos do tipo Int, e que retorna um valor do tipo Int."

Aqui está outro exemplo, para uma função sem parâmetros ou valor de retorno:

func imprimeOlaMundo() {
print("Olá, mundo")
}

O tipo desta função é () -> Void, ou seja, "uma função que não tem parâmetros e retorna Void."

Usando Tipos de Função

Você utiliza tipos de função da mesma forma que quaisquer outros tipos em Swift. Por exemplo, você pode definir uma constante ou variável para ser de um tipo de função e atribuir uma função apropriada a essa variável:

var funcaoMatematica: (Int, Int) -> Int = somarDoisInteiros

Isso pode ser lido como:

"Defina uma variável chamada funcaoMatematica, que tem um tipo de 'uma função que recebe dois valores Int e retorna um valor Int.' Defina esta nova variável para referenciar a função chamada somarDoisInteiros."

A função somarDoisInteiros(::) tem o mesmo tipo que a variável funcaoMatematica, e assim esta atribuição é permitida pelo verificador de tipos do Swift.

Agora você pode chamar a função atribuída com o nome funcaoMatematica:

print("Resultado: \(funcaoMatematica(2, 3))")
// Imprime "Resultado: 5"

Uma função diferente com o mesmo tipo de correspondência pode ser atribuída à mesma variável, da mesma forma que para tipos não funcionais:

funcaoMatematica = multiplicarDoisInteiros
print("Resultado: \(funcaoMatematica(2, 3))")
// Exibe "Resultado: 6"

Como acontece com qualquer outro tipo, você pode deixar que o Swift infira o tipo de função quando atribui uma função a uma constante ou variável:

let outraFuncaoMatematica = somarDoisInteiros
// outraFuncaoMatematica é inferida como sendo do tipo (Int, Int) -> Int

Tipos de Função como Tipos de Parâmetro

Você pode usar um tipo de função, como (Int, Int) -> Int, como tipo de parâmetro para outra função. Isso permite deixar alguns aspectos da implementação de uma função para o chamador da função fornecer quando a função é chamada.

Aqui está um exemplo para imprimir os resultados das funções matemáticas mencionadas anteriormente:

func imprimirResultadoMatematico(_ funcaoMatematica: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Resultado: \(funcaoMatematica(a, b))")
}
imprimirResultadoMatematico(somarDoisInteiros, 3, 5)
// Imprime "Resultado: 8"

Este exemplo define uma função chamada imprimirResultadoMatematico(_:_:_:), que tem três parâmetros. O primeiro parâmetro é chamado de funcaoMatematica e é do tipo (Int, Int) -> Int. Você pode passar qualquer função desse tipo como argumento para este primeiro parâmetro. Os segundo e terceiro parâmetros são chamados de a e b, e ambos são do tipo Int. Eles são usados como os dois valores de entrada para a função matemática fornecida.

Quando imprimirResultadoMatematico(_:_:_:) é chamado, é passada a função somarDoisInteiros(_:_:) e os valores inteiros 3 e 5. Ela chama a função fornecida com os valores 3 e 5, e imprime o resultado 8.

O papel de imprimirResultadoMatematico(_:_:_:) é imprimir o resultado de uma chamada para uma função matemática de um tipo apropriado. Não importa o que a implementação dessa função realmente faz — importa apenas que a função seja do tipo correto. Isso permite que imprimirResultadoMatematico(_:_:_:) repasse parte de sua funcionalidade para o chamador da função de maneira segura em termos de tipo.

Tipos de Função como Tipos de Retorno

Você pode usar um tipo de função como o tipo de retorno de outra função. Você faz isso escrevendo um tipo de função completo imediatamente após a seta de retorno (->) da função que retorna.

O próximo exemplo define duas funções simples chamadas avancarUmPasso(_:) e recuarUmPasso(_:). A função avancarUmPasso(_:) retorna um valor um a mais do que seu valor de entrada, e a função recuarUmPasso(_:) retorna um valor um a menos do que seu valor de entrada. Ambas as funções têm um tipo de (Int) -> Int:

func avancarUmPasso(_ entrada: Int) -> Int {
return entrada + 1
}

func recuarUmPasso(_ entrada: Int) -> Int {
return entrada - 1
}

Aqui está uma função chamada escolherFuncaoPasso(recuar:), cujo tipo de retorno é (Int) -> Int. A função escolherFuncaoPasso(recuar:) retorna a função avancarUmPasso(_:) ou a função recuarUmPasso(_:) com base em um parâmetro booleano chamado recuar:

func escolherFuncaoPasso(recuar: Bool) -> (Int) -> Int {
return recuar ? recuarUmPasso : avancarUmPasso
}

Agora você pode usar escolherFuncaoPasso(recuar:) para obter uma função que avançará em uma direção ou outra:

var valorAtual = 3
let moverMaisPertoDoZero = escolherFuncaoPasso(recuar: valorAtual > 0)
// moverMaisPertoDoZero agora se refere à função recuarUmPasso()

O exemplo acima determina se é necessário um passo positivo ou negativo para mover uma variável chamada valorAtual progressivamente mais perto de zero. valorAtual tem um valor inicial de 3, o que significa que valorAtual > 0 retorna true, fazendo com que escolherFuncaoPasso(recuar:) retorne a função recuarUmPasso(_:). Uma referência à função retornada é armazenada em uma constante chamada moverMaisPertoDoZero.

Agora que moverMaisPertoDoZero se refere à função correta, pode ser usado para contar até zero:

print("Contando até zero:")
// Contando até zero:
while valorAtual != 0 {
print("\(valorAtual)... ")
valorAtual = moverMaisPertoDoZero(valorAtual)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

Funções Aninhadas

Todas as funções que você encontrou até agora neste capítulo têm sido exemplos de funções globais, que são definidas em um escopo global. Você também pode definir funções dentro dos corpos de outras funções, conhecidas como funções aninhadas.

As funções aninhadas são ocultas do mundo exterior por padrão, mas ainda podem ser chamadas e usadas pela função que as envolve. Uma função envolvente também pode retornar uma de suas funções aninhadas para permitir que a função aninhada seja usada em outro escopo.

Você pode reescrever o exemplo de escolherFuncaoPasso(recuar:) acima para usar e retornar funções aninhadas:

func escolherFuncaoPasso(recuar: Bool) -> (Int) -> Int {
func avancarUmPasso(entrada: Int) -> Int { return entrada + 1 }
func recuarUmPasso(entrada: Int) -> Int { return entrada - 1 }
return recuar ? recuarUmPasso : avancarUmPasso
}
var valorAtual = -4
let moverMaisPertoDoZero = escolherFuncaoPasso(recuar: valorAtual > 0)
// moverMaisPertoDoZero agora se refere à função aninhada avancarUmPasso()
while valorAtual != 0 {
print("\(valorAtual)... ")
valorAtual = moverMaisPertoDoZero(valorAtual)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!