Menu
Coddy logo textTech

Retornando Closures

Parte da seção Lógica e Fluxo do Journey de Swift da Coddy — lição 41 de 56.

Você viu o makeCounter retornar um closure. O mesmo truque permite que você construa um comportamento configurável: receba parâmetros uma vez e obtenha de volta uma função que os utiliza muitas vezes.

func multiplier(_ k: Int) -> (Int) -> Int {
    return { n in n * k }
}

let triple = multiplier(3)
let tenfold = multiplier(10)
print(triple(4))                  // 12
print(tenfold(4))                 // 40

A closure retornada captura k, então cada chamada de multiplier(...) produz uma closure totalmente nova com seu próprio k.

Este padrão é o cerne do código de "estratégia" em Swift: escreva uma função que recebe uma configuração e retorna um closure, então passe o closure para map, filter, sorted(by:), ou qualquer outro lugar onde um valor em formato de função seja esperado.

challenge icon

Desafio

Médio

Construa duas fábricas de closures:

  • greaterThan(_ k: Int) -> (Int) -> Bool: retorna um predicado que é true quando seu argumento é estritamente maior que k
  • scaleBy(_ k: Int) -> (Int) -> Int: retorna uma função que multiplica seu argumento por k

Leia três linhas:

  1. Um número inteiro threshold
  2. Um número inteiro scale
  3. Uma lista de inteiros separados por vírgula, os nums

Imprima três linhas:

  1. Os números acima do limite (filtre com a closure de greaterThan), unidos por ,
  2. Os mesmos números, escalonados (mapeie com scaleBy), unidos por ,
  3. Quantos números passaram pelo filtro

Para a entrada 5 / 3 / 2,7,3,8,9, a saída é:

7,8,9
21,24,27
3

Folha de consulta

Uma fábrica de closures (closure factory) é uma função que captura um parâmetro e retorna uma nova closure configurada por ele:

func multiplier(_ k: Int) -> (Int) -> Int {
    return { n in n * k }
}

let triple = multiplier(3)
print(triple(4))   // 12

Cada chamada produz uma closure novinha em folha com seu próprio valor capturado de k. As closures retornadas podem ser passadas diretamente para map, filter, sorted(by:), etc.:

func greaterThan(_ k: Int) -> (Int) -> Bool {
    return { n in n > k }
}

let nums = [2, 7, 3, 8, 9]
let filtered = nums.filter(greaterThan(5))  // [7, 8, 9]
let scaled = filtered.map(multiplier(3))    // [21, 24, 27]

Experimente você mesmo

let threshold = Int(readLine()!)!
let scale = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }

// TODO: maiorQue, escalarPor; filtrar depois mapear; imprimir unidos e contar
quiz iconTeste seus conhecimentos

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