Capturando Valores
Parte da seção Lógica e Fluxo do Journey de Swift da Coddy — lição 40 de 56.
Um closure lembra as variáveis que estavam no escopo quando foi criado. O corpo do closure pode lê-las e até modificá-las mais tarde, mesmo após a função externa ter retornado. Isso é chamado de captura.
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1
return count
}
}
let next = makeCounter()
print(next()) // 1
print(next()) // 2
print(next()) // 3Cada chamada makeCounter fornece um count novinho em folha, então dois contadores nunca compartilham o estado:
let a = makeCounter()
let b = makeCounter()
print(a()) // 1
print(b()) // 1
print(a()) // 2A captura é o que torna as closures mais poderosas do que funções comuns: elas carregam estado consigo. Você verá o mesmo truque em JavaScript, Python e muitas outras linguagens.
Desafio
MédioConstrua uma pequena fábrica de contadores.
Defina uma função makeCounter(start: Int, step: Int) que retorna uma closure do tipo () -> Int. Cada chamada para a closure retorna o próximo valor: a primeira chamada retorna start, a próxima retorna start + step, a próxima start + 2*step, e assim por diante.
Leia três inteiros da entrada: start, step, e n. Construa um contador com start e step, então chame-o n vezes e imprima cada resultado em sua própria linha.
Para a entrada 5 / 3 / 4, a saída é:
5
8
11
14Folha de consulta
Closures capturam variáveis de seu escopo circundante, carregando estado mesmo após a função externa retornar:
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1
return count
}
}
let next = makeCounter()
print(next()) // 1
print(next()) // 2Cada chamada para a função de fábrica cria uma variável capturada independente — dois contadores nunca compartilham estado.
Experimente você mesmo
let start = Int(readLine()!)!
let step = Int(readLine()!)!
let n = Int(readLine()!)!
// TODO: makeCounter(start:step:) -> () -> Int que captura o valor atual
// então chame-a n vezes e imprima cada resultado
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica e Fluxo
1Strings a Fundo
Contagem e ÍndicesCase e TrimBusca em StringsDivisão e JunçãoSubstituindo SubstringsRecapitulação - Verificação de Nome de Usuário4Conjuntos
Criando ConjuntosUnião e InterseçãoSubtração e Diferença SimétricaSubconjunto e SuperconjuntoRecapitulação - Filtro de Tags7Projeto - Monitor de Hábitos
Visão Geral do ProjetoMarcar como Concluído10Projeto - Mecanismo de Quiz
Visão Geral do ProjetoFazer Perguntas2Intervalos e Strides
Fechado vs Meio-AbertoStrideMétodos de IntervaloIntervalos no SwitchRecapitulação - Grade de Calendário5Funções de Ordem Superior Parte 1
MapFilterReduceEncadeando map, filter, reduceRecapitulação - Estatísticas de Palavras