Последующие замыкания
Часть раздела Логика и управление потоком путешествия по Swift на Coddy — урок 39 из 56.
Когда замыкание является последним аргументом функции, вы можете написать его за пределами круглых скобок. Это форма trailing-closure, и именно так код на Swift читается естественно.
let nums = [1, 2, 3]
// Стандартная форма
let a = nums.map({ $0 * 2 })
// Форма с последующим замыканием
let b = nums.map { $0 * 2 }Если замыкание является единственным аргументом, круглые скобки тоже исчезают. Вот почему всё, что вы видели до сих пор, читается как пользовательская управляющая конструкция.
Вы можете писать свои собственные функции, которые принимают замыкания таким же образом:
func repeatN(_ n: Int, action: () -> Void) {
for _ in 0..<n {
action()
}
}
repeatN(3) {
print("hi")
}Форма с замыканием в конце (trailing closure) делает так, что repeatN(3) { ... } читается как встроенный цикл. В этом и заключается суть: управляющие конструкции, которые вы создаете сами, выглядят точно так же, как и те, что входят в стандартную библиотеку.
Задание
ЛегкоОпределите функцию collect, которая:
- Принимает целое число
nи замыканиеbuilder: (Int) -> String - Вызывает
builderдля каждогоiот1доn(включительно) и возвращает массив результирующих строк
Считайте целое число из stdin, вызовите collect с этим числом, используя замыкание (trailing closure), которое создает "i=<i>" для каждого значения, и выведите объединенный результат через ,.
Для входного значения 4 результатом будет i=1,i=2,i=3,i=4.
Шпаргалка
Синтаксис последующего замыкания: когда замыкание является последним аргументом, его можно написать за пределами круглых скобок. Если это единственный аргумент, круглые скобки опускаются полностью.
let nums = [1, 2, 3]
let a = nums.map({ $0 * 2 }) // стандартный вариант
let b = nums.map { $0 * 2 } // последующее замыканиеПользовательские функции могут принимать замыкания таким же образом, благодаря чему они читаются как встроенные управляющие конструкции:
func repeatN(_ n: Int, action: () -> Void) {
for _ in 0..<n {
action()
}
}
repeatN(3) {
print("hi")
}Попробуйте сами
let n = Int(readLine()!)!
// TODO: func collect(_ n:Int, builder:(Int)->String) -> [String]
// затем вызовите collect(n) { ... } и выведите результат, объединив через ","
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Строки в деталях
Подсчет и индексыРегистр и удаление пробеловПоиск в строкахРазделение и объединениеЗамена подстрокИтоги — Проверка имени пользователя4Множества
Создание множествОбъединение и пересечениеРазность и симметрическая разностьПодмножество и надмножествоИтоги — Фильтр тегов7Проект — Трекер привычек
Обзор проектаОтметить выполнение10Проект — Движок викторины
Обзор проектаЗадаем вопросы2Диапазоны и шаги
Закрытые и полуоткрытыеШагМетоды диапазоновДиапазоны в SwitchИтоги: Сетка календаря8Замыкания
Основы замыканийПоследующие замыканияЗахват значенийВозврат замыканийСобственные функции высшего порядкаИтоги — Pipeline Builder