Подтвердить что ты не робот

Когда использовать forEach (_:) вместо того, чтобы в?

Как указано в Array и Dictionary forEach(_:) Методы экземпляра:

Вызывает данное замыкание на каждом элементе последовательности в том же порядок как цикл for-in.

Тем не менее, адаптирован из Обзор последовательности:

Последовательность представляет собой список значений, которые вы можете выполнить через один время. Наиболее распространенный способ итерации по элементам последовательности заключается в использовании for-in цикла.

Предположим, что итерационная последовательность forEach(_:) или for in:

let closedRange = 1...3

for element in closedRange { print(element) } // 1 2 3

closedRange.forEach { print($0) } // 1 2 3

Или (массив):

let array = [1, 2, 3]

for element in array { print(element) } // 1 2 3

array.forEach { print($0) } // 1 2 3

Выдает тот же результат.

Почему forEach(_:) существует даже? Какая польза от использования его вместо цикла for in? будут ли они одинаковыми с точки зрения точки зрения?

В качестве предположения он может быть синтаксическим сахаром, особенно при работе с функциональным программированием.

4b9b3361

Ответ 1

Для forEach нет преимуществ по производительности. Фактически, если вы посмотрите на исходный код, функция forEach фактически просто выполняет for - in. Для создания релизов служебные данные по производительности этой функции при простом использовании for - in сами по себе являются несущественными, хотя для отладочных сборников это приводит к заметному влиянию производительности.

Основное преимущество forEach реализуется, когда вы выполняете функциональное программирование, вы можете добавить его в цепочку функциональных вызовов, не сохраняя прежний результат в отдельной переменной, которая вам понадобится, если вы использовали for - in. Итак, вместо:

let objects = array.map { ... }
    .filter { ... }

for object in objects {
    ...
}

Вместо этого вы можете оставаться внутри функциональных шаблонов программирования:

array.map { ... }
    .filter { ... }
    .forEach { ... }

В результате получается функциональный код, более сжатый с меньшим синтаксическим шумом.

FWIW, документация для Array, Dictionary и Sequence все напоминают нам ограничения, введенные forEach, а именно:

  • Вы не можете использовать оператор break или continue для выхода из текущего вызов закрытия body или пропустить последующие вызовы.

  • Использование оператора return в закрытии body будет только с текущий вызов body, а не из любой внешней области, и не будет пропускать последующие вызовы.

Ответ 2

Недавно я столкнулся с прецедентом, где использование forEach было предпочтительным осязаемым способом for in. Скажем, вы хотите удалить все подслои из слоя. Заявление, подобное приведенному ниже, не работает, так как вам необходимо развернуть [CALayer]

for layer in self.videoContainerView.layer.sublayers!

Если подслойки равны нулю, вы получите сбой. Это заставляет вас проверить, есть ли подслои в первую очередь. Однако a forEach делает это намного проще, чем в следующем:

self.videoContainerView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }

Ответ 3

Они более или менее взаимозаменяемы, но есть два важных отличия.

  • break/continue работают только в for .. in
  • return в forEach выйдет из закрытия, но не остановит итерацию.

Причиной этого является то, что for .. in представляет собой специальную форму на языке (что позволяет прерывать и продолжать работать так, как вы ожидаете). Это то, что вы не можете реализовать одинаково, используя сам язык.

Однако forEach не является специальной формой и может быть повторно реализован идентично, записав его как функцию.

extension Sequence {
    func myOwnForEach(_ body: (Self.Element) throws -> Void) rethrows {
        let it = Self.makeIterator()
        while let item = it.next() {
            body(item)
        }
    }
}