Skip to content

Commit

Permalink
Add rule to prefer for loops over functional forEach(…) method (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
calda authored Aug 8, 2023
1 parent 741e55b commit b408d36
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,40 @@ _You can enable the following settings in Xcode by running [this script](resourc

</details>

* <a id='prefer-for-loop-over-forEach'></a>(<a href='#prefer-for-loop-over-forEach'>link</a>) **Prefer using `for` loops over the functional `forEach()` method**, unless using `forEach()` as the last element in a functional chain. [![SwiftFormat: forLoop](https://img.shields.io/badge/SwiftFormat-forLoop-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#forLoop)

<details>

#### Why?
For loops are more idiomatic than the `forEach()` method, and are typically familiar to all developers who have experience with C-family languages.

For loops are also more expressive than the `forEach()` method. For loops support the `return`, `continue`, and `break` control flow keywords, while `forEach()` only supports `return` (which has the same behavior as `continue` in a for loop).

```swift
// WRONG
planets.forEach { planet in
planet.terraform()
}

// WRONG
planets.forEach {
$0.terraform()
}

// RIGHT
for planet in planets {
planet.terraform()
}

// ALSO FINE, since forEach is useful when paired with other functional methods in a chain.
planets
.filter { !$0.isGasGiant }
.map { PlanetTerraformer(planet: $0) }
.forEach { $0.terraform() }
```

</details>

* <a id='omit-internal-keyword'></a>(<a href='#omit-internal-keyword'>link</a>) **Omit the `internal` keyword** when defining types, properties, or functions with an internal access control level. [![SwiftFormat: redundantInternal](https://img.shields.io/badge/SwiftFormat-redundantInternal-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#redundantInternal)

<details>
Expand Down Expand Up @@ -1564,6 +1598,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
}
```

</details>

* <a id='anonymous-trailing-closures'></a>(<a href='#anonymous-trailing-closures'>link</a>) **Prefer trailing closure syntax for closure arguments with no parameter name.** [![SwiftFormat: trailingClosures](https://img.shields.io/badge/SwiftFormat-trailingClosures-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#trailingClosures)

<details>
Expand All @@ -1584,6 +1620,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
planets.first { $0.isGasGiant }
```

</details>

### Operators

* <a id='infix-operator-spacing'></a>(<a href='#infix-operator-spacing'>link</a>) **Infix operators should have a single space on either side.** Prefer parenthesis to visually group statements with many operators rather than varying widths of whitespace. This rule does not apply to range operators (e.g. `1...3`) and postfix or prefix operators (e.g. `guest?` or `-1`). [![SwiftLint: operator_usage_whitespace](https://img.shields.io/badge/SwiftLint-operator__usage__whitespace-007A87.svg)](https://realm.github.io/SwiftLint/operator_usage_whitespace)
Expand Down
2 changes: 2 additions & 0 deletions Sources/AirbnbSwiftFormatTool/airbnb.swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
--someAny disabled # opaqueGenericParameters
--elseposition same-line #elseOnSameLine
--guardelse next-line #elseOnSameLine
--oneLineForEach wrap #forLoop

# We recommend a max width of 100 but _strictly enforce_ a max width of 130
--maxwidth 130 # wrap
Expand Down Expand Up @@ -89,3 +90,4 @@
--rules trailingClosures
--rules elseOnSameLine
--rules sortTypealiases
--rules forLoop

0 comments on commit b408d36

Please sign in to comment.