什么时候使用 forEach(_:) 而不是 for in?
When to use forEach(_:) instead of for in?
如 Array and Dictionary forEach(_:)
实例方法中所述:
Calls the given closure on each element in the sequence in the same
order as a for-in loop.
尽管如此,改编自Sequence Overview:
A sequence is a list of values that you can step through one at a
time. The most common way to iterate over the elements of a sequence
is to use a for-in loop.
暗示 forEach(_:)
或 for in
的迭代序列:
let closedRange = 1...3
for element in closedRange { print(element) } // 1 2 3
closedRange.forEach { print([=10=]) } // 1 2 3
或(数组):
let array = [1, 2, 3]
for element in array { print(element) } // 1 2 3
array.forEach { print([=11=]) } // 1 2 3
会给出相同的输出。
为什么 forEach(_:)
还存在?即使用它而不是 for in
循环有什么好处?从性能的角度来看它们是否相同?
作为一个假设,它可能是一种语法糖,尤其是在使用 函数式编程时 。
forEach
没有提供任何性能优势。事实上,if you look at the source code,forEach
函数实际上只是执行for
-in
。对于发布版本,此函数的性能开销比简单地使用 for
-in
本身是无关紧要的,但对于调试版本,它会导致可观察到的性能影响。
forEach
的主要优势在您进行函数式编程时体现出来,您可以将其添加到函数调用链中,而无需将先前的结果保存到您需要的单独变量中如果您使用 for
-in
语法。所以,而不是:
let objects = array.map { ... }
.filter { ... }
for object in objects {
...
}
您可以改用函数式编程模式:
array.map { ... }
.filter { ... }
.forEach { ... }
结果是功能代码更简洁,语法噪音更少。
FWIW,Array, Dictionary, and Sequence 的文档都提醒我们 forEach
引入的限制,即:
You cannot use a break
or continue
statement to exit the current
call of the body
closure or skip subsequent calls.
Using the return
statement in the body
closure will exit only from
the current call to body
, not from any outer scope, and won't skip
subsequent calls.
它们或多或少可以互换,但有两个重要区别。
break
/continue
仅适用于 for .. in
return
in 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)
}
}
}
我最近 运行 研究了一个用例,其中使用 forEach
在有形的方式上比 for in
更可取。假设您要从图层中删除所有子图层。像下面这样的语句不起作用,因为您需要打开 [CALayer]
for layer in self.videoContainerView.layer.sublayers!
如果子层为零,您将遇到崩溃。这会强制您首先检查是否有子层。但是,forEach
使这变得更简单,如下所示:
self.videoContainerView.layer.sublayers?.forEach { [=11=].removeFromSuperlayer() }
除了上述答案之外,将 for
循环与 forEach
区分开来的另一个原因是,对于 for
循环,我们还可以选择使用 where
来实现该逻辑基于模式匹配,比如
for adBanner in adBanners where !adBanner.isLoading {
上述与控制流相关的特性是 for 循环如此强大的原因,但如果我们不需要那种级别的控制,则使用对 forEach 的调用可能会让我们的代码看起来稍微简单一些。
简而言之,使用 for
循环可以让我们更好地控制迭代
如 Array and Dictionary forEach(_:)
实例方法中所述:
Calls the given closure on each element in the sequence in the same order as a for-in loop.
尽管如此,改编自Sequence Overview:
A sequence is a list of values that you can step through one at a time. The most common way to iterate over the elements of a sequence is to use a for-in loop.
暗示 forEach(_:)
或 for in
的迭代序列:
let closedRange = 1...3
for element in closedRange { print(element) } // 1 2 3
closedRange.forEach { print([=10=]) } // 1 2 3
或(数组):
let array = [1, 2, 3]
for element in array { print(element) } // 1 2 3
array.forEach { print([=11=]) } // 1 2 3
会给出相同的输出。
为什么 forEach(_:)
还存在?即使用它而不是 for in
循环有什么好处?从性能的角度来看它们是否相同?
作为一个假设,它可能是一种语法糖,尤其是在使用 函数式编程时 。
forEach
没有提供任何性能优势。事实上,if you look at the source code,forEach
函数实际上只是执行for
-in
。对于发布版本,此函数的性能开销比简单地使用 for
-in
本身是无关紧要的,但对于调试版本,它会导致可观察到的性能影响。
forEach
的主要优势在您进行函数式编程时体现出来,您可以将其添加到函数调用链中,而无需将先前的结果保存到您需要的单独变量中如果您使用 for
-in
语法。所以,而不是:
let objects = array.map { ... }
.filter { ... }
for object in objects {
...
}
您可以改用函数式编程模式:
array.map { ... }
.filter { ... }
.forEach { ... }
结果是功能代码更简洁,语法噪音更少。
FWIW,Array, Dictionary, and Sequence 的文档都提醒我们 forEach
引入的限制,即:
You cannot use a
break
orcontinue
statement to exit the current call of thebody
closure or skip subsequent calls.Using the
return
statement in thebody
closure will exit only from the current call tobody
, not from any outer scope, and won't skip subsequent calls.
它们或多或少可以互换,但有两个重要区别。
break
/continue
仅适用于for .. in
return
inforEach
将退出闭包,但不会停止迭代。
原因是 for .. in
是语言中的一种 特殊形式 (允许中断并继续按预期工作)。这是您无法使用语言本身以相同方式实现的东西。
但是,forEach
不是特殊形式,可以通过将其编写为函数来重新实现。
extension Sequence {
func myOwnForEach(_ body: (Self.Element) throws -> Void) rethrows {
let it = Self.makeIterator()
while let item = it.next() {
body(item)
}
}
}
我最近 运行 研究了一个用例,其中使用 forEach
在有形的方式上比 for in
更可取。假设您要从图层中删除所有子图层。像下面这样的语句不起作用,因为您需要打开 [CALayer]
for layer in self.videoContainerView.layer.sublayers!
如果子层为零,您将遇到崩溃。这会强制您首先检查是否有子层。但是,forEach
使这变得更简单,如下所示:
self.videoContainerView.layer.sublayers?.forEach { [=11=].removeFromSuperlayer() }
除了上述答案之外,将 for
循环与 forEach
区分开来的另一个原因是,对于 for
循环,我们还可以选择使用 where
来实现该逻辑基于模式匹配,比如
for adBanner in adBanners where !adBanner.isLoading {
上述与控制流相关的特性是 for 循环如此强大的原因,但如果我们不需要那种级别的控制,则使用对 forEach 的调用可能会让我们的代码看起来稍微简单一些。
简而言之,使用 for
循环可以让我们更好地控制迭代