What Are the Advantages Swift Deprecates C-Style for Statement

What are the advantages Swift deprecates C-style for statement?

For details, see Swift Evolution - Remove C style for-loops

To quote the reasoning:

  1. Both for-in and stride provide equivalent behavior using Swift-coherent approaches without being tied to legacy terminology.
  2. There is a distinct expressive disadvantage in using for-loops compared to for-in in succinctness
  3. for-loop implementations do not lend themselves to use with collections and other core Swift types.
  4. The for-loop encourages use of unary incrementors and decrementors, which will be soon removed from the language.
  5. The semi-colon delimited declaration offers a steep learning curve from users arriving from non C-like languages
  6. If the for-loop did not exist, I doubt it would be considered for inclusion in Swift 3.

In summary: there are better ways (more expressive) than a C-style for-loop to iterate in Swift.

Some examples:

for-in over a range:

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)")
}

For arrays (and other sequences) we have many options (the following is not a complete list):

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)")
}

Also note that if you are converting an array to another array, almost always you want to use array.filter or array.map or a combination of them.

For all Strideable types we can use the stride method to generate indices, for example:

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)")
}

With arrays we can do:

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)")
}

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

It was proposed and accepted to remove the ++ and -- operators from the Swift language in an upcoming release, therefore the warning you're seeing is to help you avoid these types of constructs in your code before it is removed. (Please reference the link for a full explanation as well as the advantages and disadvantages that they provide.)

Please note that C-Style loops will also be deprecated in the near future according to the following proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md

Not knowing exactly what kind of logic you need to implement I don't feel confident recommending a solution, however in accordance with the above proposals I would recommend that you may want to become familiar with the Swift for-in and stride statements. Or, as another person recommended, using a while loop may also be appropriate.

c-style for statement deprecated with a twist

Might be best to go with a while loop:

var totalHeight: CGFloat = 0
while totalHeight < 2.0 * Configurations.sharedInstance.heightGame {
// Loop code goes here

totalHeight += backgroundImage.size.height
}

Converting a C-style for loop that uses division for the step to Swift 3

MartinR's solution is very generic and useful and should be part of your toolbox.

Another approach is to rephrase what you want: the powers of two from 7 down to 0.

for i in (0...7).reversed().map({ 1 << $0 }) {
print(i)
}

Replacement for c style loop with modulo

"while" should be the best:

var i = startIndex
while i != endIndex {
i = (i + 1) % arrCount
}

The ++ and -- operators have been deprecated Xcode 7.3

A full explanation here from Chris Lattner, Swift's creator. I'll summarize the points:

  1. It's another function you have to learn while learning Swift
  2. Not much shorter than x += 1
  3. Swift is not C. Shouldn't carry them over just to please C programmers
  4. Its main use is in C-style for loop: for i = 0; i < n; i++ { ... }, which Swift has better alternatives, like for i in 0..<n { ... } (C-style for loop is going out as well)
  5. Can be tricky to read and maintain, for eg, what's the value of x - ++x or foo(++x, x++)?
  6. Chris Lattner doesn't like it.

For those interested (and to avoid link rot), Lattner's reasons in his own words are:

  1. These operators increase the burden to learn Swift as a first programming language - or any other case where you don't already know these operators from a different language.

  2. Their expressive advantage is minimal - x++ is not much shorter than x += 1.

  3. Swift already deviates from C in that the =, += and other assignment-like operations returns Void (for a number of reasons). These operators are inconsistent with that model.

  4. Swift has powerful features that eliminate many of the common reasons you'd use ++i in a C-style for loop in other languages, so these are relatively infrequently used in well-written Swift code. These features include the for-in loop, ranges, enumerate, map, etc.

  5. Code that actually uses the result value of these operators is often confusing and subtle to a reader/maintainer of code. They encourage "overly tricky" code which may be cute, but difficult to understand.

  6. While Swift has well defined order of evaluation, any code that depended on it (like foo(++a, a++)) would be undesirable even if it was well-defined.

  7. These operators are applicable to relatively few types: integer and floating point scalars, and iterator-like concepts. They do not apply to complex numbers, matrices, etc.

Finally, these fail the metric of "if we didn't already have these, would we add them to Swift 3?"

Advantage of telling the Swift Compiler an object's type, instead of inferring?

There’s zero runtime efficiency difference between the two. During compilation, Swift is inferring the type and writing it in for you. But once compiled, the two statements are identical.

It’s purely a question of readability and, occasionally, compiler efficiency.

Readability because in the statement let image: UIImage = UIImage(), the double appearance of UIImage is just clutter. And in cases of more complex types, it’s pretty much essential – no-one wants to write let keys: LazyForwardCollection<MapCollectionView<Dictionary<String, Int>, String>> = dict.keys when they can write let keys = dict.keys.

Compiler efficiency because occasionally you’ll find that a particularly ambiguous type (literals of literals are notorious for this) where lots of overloads need to be resolved can compile a lot faster if you explicitly name the type on the left-hand side. But this is just a question of how fast it compiles, not how fast it runs once it has compiled.

Deprecation and other attributes of methods in Swift, how?

Swift has an available attribute that you can use for this. It's available arguments include

  • introduced
  • deprecated
  • obsoleted
  • message
  • renamed.

Or for the example you gave:

@available(*, unavailable, message: "init is unavailable, use initWithFrame")
init() {

}

@available(*, deprecated, message: "use shareWithPars: instead")
class func shareWithParams(params: NSDictionary) {

}

For more information on these attributes, check out the Attributes section in The Swift Programming Language. (currently page 627)

++' is deprecated: it will be removed in Swift 3

Since Swift 2.2, you should use += 1 or -= 1 instead.

And after looking up Swift's evolution, there are some reasons for removing these operators:

  1. These operators increase the burden to learn Swift as a first programming language - or any other case where you don't already know these operators from a different language.

  2. Their expressive advantage is minimal - x++ is not much shorter than x += 1.

  3. Swift already deviates from C in that the =, += and other assignment-like operations returns Void (for a number of reasons). These operators are inconsistent with that model.

  4. Swift has powerful features that eliminate many of the common reasons you'd use ++i in a C-style for loop in other languages, so these are relatively infrequently used in well-written Swift code. These features include the for-in loop, ranges, enumerate, map, etc.

  5. Code that actually uses the result value of these operators is often confusing and subtle to a reader/maintainer of code. They encourage "overly tricky" code which may be cute, but difficult to understand.

  6. While Swift has well defined order of evaluation, any code that depended on it (like foo(++a, a++)) would be undesirable even if it was well-defined.

  7. These operators are applicable to relatively few types: integer and floating point scalars, and iterator-like concepts. They do not apply to complex numbers, matrices, etc.

Finally, these fail the metric of "if we didn't already have these, would we add them to Swift 3?"

Please check out Swift evolution for more info.



Related Topics



Leave a reply



Submit