[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` 

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.


More information about the swift-evolution mailing list