[swift-evolution] [Pitch] Retiring `where` from for-in loops
Károly Lőrentey
karoly at lorentey.hu
Fri Jun 10 10:08:13 CDT 2016
On 2016-06-10 11:39:34 +0000, Leonardo Pessoa via swift-evolution said:
> I would vow to remove where clauses altogether. Most of the times I
> used it in ifs, fors and switches I ended up thinking it hardened
> readability of my code (perhaps because of placement, but I do not
> think alternatives made it more readable) and so it was my decision to
> stop using where whenever possible in my code. Since Erica's
> performance test pointed out using guard is nearly as fast as using
> where and the core team is removing wheres from ifs, I think the ones
> in fors could go next.
Interestingly, I find where clauses in `for` to be a useful tool to
*improve* readibility. To me, it flows much better to write & read this:
for (start, duration) in days where calendar.isDateInWeekend(start) {
...
}
rather than this:
for (start, duration) in days {
guard calendar.isDateInWeekend(start) else { continue }
...
}
or this:
for (start, duration) in days.filter({ calendar.isDateInWeekend($0.0) }) {
...
}
Of these three, I'd argue the first is the easiest to understand for a
person who's never seen Swift code before. (Admittedly I doubt that's
something languages should be optimized for, though.) The extra
punctuation and the use of $0 instead of the loop's bindings makes the
third approach seem especially noisy & scary.
Obviously, editorial tools like this aren't essential, and I could
easily adapt to live without such syntactic sugar. But I do not like
the idea of systematically ridding the language of such charming
constructs when there is no technical reason to do so. SE-0099 fixed a
technical problem with the syntax of a shorthand construct, without
removing it from the language. It did not bring back Swift 1's `if`
pyramids.
Moreover, Erica is absolutely right about `switch`: while `where`
clauses are arguably non-essential in `for` loops, `switch` statements
would lose a great deal of their expressive power without them. For
example, in the following snippet (taken from a lexer in SwiftPM), all
cases are logically at the same level. I think it's a win that Swift
allows them to be expressed as such, and I'd strongly object to a
proposal that removed this capability.
switch c {
case UInt8(ascii: "\n"): ...
case UInt8(ascii: "#"): ...
case let c where c.isSpace(): ...
case UInt8(ascii: "\""): ...
case let c where c.isNumberInitialChar(): ...
case let c where c.isIdentifierChar(): ...
case UInt8(ascii: ","): ...
case UInt8(ascii: "="): ...
case UInt8(ascii: "["): ...
case UInt8(ascii: "]"): ...
case UInt8(ascii: "."): ...
default: ...
}
Obviously, we could rewrite this to use a single `if` ladder, but I
think most would not find that an improvement.
(The same argument applies to `catch` statements, although with less force.)
As long as `where` is kept in `switch` and `catch`, and as long the
grammar is unambiguous, I think there is little point to removing where
clauses from `for`. To improve consistency, I'd not mind if SE-0099
kept `where` as an alternative way to spell `,` in `if` statements, too.
--
Károly
@lorentey
More information about the swift-evolution
mailing list