【问题标题】:What are the advantages Swift deprecates C-style for statement? [closed]Swift 弃用 C 风格的 for 语句有什么优势? [关闭]
【发布时间】:2016-07-10 20:38:57
【问题描述】:

我刚刚将 XCode 更新到 7.3,并且对我的代码的警告数量感到惊讶,尤其是这个:

C-style for statement is deprecated and will be removed in a future version of Swift 

我看到了一些解决方案:

for idx in 0...<10 {}

for idx in 10.stride(to: 0, by: -1)

说真的,为什么?使用 stride 然后使用 C 风格的 for 循环会更好吗?有什么优势?现在使用for循环时我很困惑。我必须反复检查以查看我是否正确使用了 for 循环。

【问题讨论】:

  • 谷歌一下。这里引用了删除它的理由...medium.com/@swiftafricanus/…
  • Swift 从未真正实现过“C 风格”for 循环,尽管语法表明它确实实现了 - 循环索引的行为与人们对 C 的期望不同(即它不是变量) - 看到这个问题/答案stackoverflow.com/questions/33219684/…
  • @vadian C-style for loop 与递增/递减运算符不同。
  • @SulthanYes,但这两个问题是相关的
  • 这不是stackoverflow.com/questions/35158422/… 的副本,因此我重新提出了这个问题。不过,它可能符合基于意见的条件。

标签: swift


【解决方案1】:

详情见Swift Evolution - Remove C style for-loops

引用推理:

  1. for-instride 都使用 Swift 一致的方法提供等效的行为,而不受旧术语的束缚。
  2. 在简洁性方面,与 for-in 相比,使用 for-loop 存在明显的表达缺陷
  3. for-loop 实现不适合与集合和其他核心 Swift 类型一起使用。
  4. for-loop 鼓励使用一元增量器和减量器,这将很快从语言中删除。
  5. 分号分隔的声明为来自非 C 类语言的用户提供了陡峭的学习曲线
  6. 如果 for 循环不存在,我怀疑它是否会被考虑包含在 Swift 3 中。

总之:在 Swift 中迭代有比 C 风格 for-loop 更好的方法(更具表现力)。

一些例子:

for-in 在一个范围内:

for i in 0 ..< 10 {
    //iterate over 0..9
    print("Index: \(i)")
}

for i in (0 ..< 10).reverse() {
    //iterate over 9..0
    print("Index: \(i)")
}

对于数组(和其他序列),我们有很多选择(以下不是完整列表):

let array = ["item1", "item2", "item3"]

array.forEach {
    // iterate over items
    print("Item: \($0)")
}

array.reverse().forEach {
    // iterate over items in reverse order
    print("Item: \($0)")
}

array.enumerate().forEach {
    // iterate over items with indices
   print("Item: \($1) at index \($0)")
}

array.enumerate().reverse().forEach {
    // iterate over items with indices in reverse order
    print("Item: \($1) at index \($0)")
}

for index in array.indices {
    // iterate using a list of indices
    let item = array[index]
    print("Item \(item) at index: \(index)")
}

另请注意,如果您要将一个数组转换为另一个数组,几乎总是希望使用array.filterarray.map 或它们的组合。

对于所有Strideable 类型,我们可以使用stride 方法来生成索引,例如:

for index in 10.stride(to: 30, by: 5) {
    // 10, 15, 20, 25 (not 30)
    print("Index: \(index)")
} 

for index in 10.stride(through: 30, by: 5) {
    // 10, 15, 20, 25, 30
    print("Index: \(index)")
}

我们可以使用数组:

for index in 0.stride(to: array.count, by: 2) {
    // prints only every second item
    let item = array[index]
    print("Item \(item) at index: \(index)")
}

【讨论】:

  • for循环块内索引发生变化如何解决?
  • @JoeHuang 在 for 循环中更改索引是一种反模式,并且一直如此,即使在 C/C++/Java 中也是如此。最佳解决方案取决于您的用例,但始终存在while { ... } 循环。
  • 当 inc/decrementer 不是 1 时不要忘记 .stride(to:by:)。
  • 在我把所有的for循环语句都改成for index in 0..some_count之后,我发现我的应用程序有时会崩溃,因为Can't form Range with end &lt; start如果some_count在执行过程中是负数。我开始怀念旧的循环语句。现在我必须使用不同类型的循环来处理所有可能性。
  • @JoeHuang 旧的for-loop 的问题在于它吞没了极端情况。新的替代方案迫使您更具表现力,明确解决所有极端情况。这使您的代码更具可读性,并在它们发生之前避免了一些错误。如果在start&lt;..end 范围内end 低于start,那么它是一个极端情况,从你的代码中应该可以立即看出你知道那个极端情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-19
  • 2017-01-14
  • 2010-09-06
  • 1970-01-01
  • 2013-05-15
相关资源
最近更新 更多