Retorno de Closures
Parte de la sección Lógica y Flujo del Journey de Swift de Coddy — lección 41 de 56.
Has visto que makeCounter devuelve un closure. El mismo truco te permite crear un comportamiento configurable: recibe parámetros una vez y obtén una función que los utilice muchas veces.
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)) // 40La clausura devuelta captura k, por lo que cada llamada a multiplier(...) produce una clausura completamente nueva con su propio k.
Este patrón es el núcleo del código de "estrategia" en Swift: escribe una función que tome una configuración y devuelva un closure, luego pasa el closure a map, filter, sorted(by:), o a cualquier otro lugar donde se espere un valor con forma de función.
Desafío
IntermedioConstruye dos fábricas de cierres (closures):
greaterThan(_ k: Int) -> (Int) -> Bool: devuelve un predicado que estruecuando su argumento es estrictamente mayor quekscaleBy(_ k: Int) -> (Int) -> Int: devuelve una función que multiplica su argumento pork
Lee tres líneas:
- Un entero
threshold - Un entero
scale - Una lista de enteros separados por comas, los
nums
Imprime tres líneas:
- Los números por encima del umbral (filtrados con el cierre de
greaterThan), unidos con, - Los mismos números, escalados (mapeados con
scaleBy), unidos con, - Cuántos pasaron el filtro
Para la entrada 5 / 3 / 2,7,3,8,9, la salida es:
7,8,9
21,24,27
3Hoja de referencia
Una fábrica de closures es una función que captura un parámetro y devuelve una nueva closure configurada por este:
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
print(triple(4)) // 12Cada llamada produce una closure completamente nueva con su propio valor capturado de k. Las closures devueltas pueden pasarse directamente a 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]Pruébalo tú mismo
let threshold = Int(readLine()!)!
let scale = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }
// TODO: mayorQue, escalarPor; filtrar luego mapear; imprimir unidos y contar
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Lógica y Flujo
1Strings a fondo
Conteo e índicesMayúsculas, minúsculas y TrimBúsqueda en StringsDividir y unirReemplazo de subcadenasResumen: Validación de usuario4Conjuntos
Crear conjuntosUnión e intersecciónResta y diferencia simétricaSubconjunto y superconjuntoResumen - Filtro de etiquetas7Proyecto - Seguimiento de hábitos
Descripción general del proyectoMarcar como completado10Proyecto - Motor de cuestionarios
Descripción general del proyectoHacer preguntas2Rangos e Intervalos
Cerrados vs. SemiabiertosSaltos (Stride)Métodos de RangosRangos en SwitchResumen - Cuadrícula de calendario5Funciones de orden superior Pt. 1
MapFilterReduceEncadenar map, filter, reduceResumen - Estadísticas de palabras