[swift-evolution] [DRAFT] Regularizing Where Grammar (was Re: Add a while clause to for loops)

Xiaodi Wu xiaodi.wu at gmail.com
Fri Jun 10 14:29:06 CDT 2016

On Fri, Jun 10, 2016 at 2:10 PM, Brent Royal-Gordon via swift-evolution <
swift-evolution at swift.org> wrote:

> > Unlike in switch statements and do loops, a for-in loop's where-clause
> is separated from the pattern it modifies.
> (I think "do loops" is supposed to be "do-catch statements"?)
> > for case? pattern in expression where-clause? code-block
> >
> > case-item-list → pattern where-clause? | pattern where-clause? ,
> case-item-list
> >
> > catch pattern? where-clause? code-block
> >
> > This separation makes the clause harder to associate with the pattern,
> can confuse users as to whether it modifies the expression or the pattern,
> and represents an inconsistency in Swift's grammar. This proposal
> regularizes the grammar to match other uses.
> I'm definitely in favor of this. (I should be—I'm listed as coauthor.)
> While I've never struggled with the `where` clause—I always assumed it was
> a filter—it never read right to me. This way does. When I say it out loud,
> "for x where x less than 10 in numbers" simply seems *far* easier to
> understand than "for x in numbers where x less than 10". There's something
> about the way the "where" combines with "for" that clarifies the entire
> statement.
> I also think this better matches the grammar of the `case` statements in a
> `switch`. Erica quotes the formal grammar above, but you can actually see
> this in running code: in a `switch` statement, a compound case with a
> `where` clause like:
>         case .foo, .bar where baz():
> Only applies the `where` clause to the last pattern (.bar, but not .foo).
> That's because the rule is that the `where` belongs to the *pattern*, not
> the entire statement.
> As a question of the proposal's drafting—as opposed to the feature being
> proposed—I do think that we should include an example of code before and
> after the change. The isOdd example ought to do.
> > Note where clauses in case conditions and optional bindings have been
> removed in SE-0099.
> I think there's actually a case to be made (no pun intended) for bringing
> `where` back in case conditions, but with an analogous movement of the
> clause's position. In other words, where (post-SE-0099) we have this
> production:
>         case-condition → "case" pattern initializer
> We would change it to:
>         case-condition → "case" pattern where-clause? initializer
> In use, this would look like:
>         if case .some(let Point.cartesian(x, y)) where x < y =
> json["rect"]?["origin"].flatMap(.init(rawValue:)) { … }

I'm concerned here about the `x < y = json...` part of this, if not for the
parser then for the human reader. I like the thought in principle though.

> Of course, the above could equally be written without a `where` clause:
>         if case .some(let Point.cartesian(x, y)) =
> json["rect"]?["origin"].flatMap(.init(rawValue:)), x < y { … }
> But nevertheless, I think it's a good idea. Why? Two reasons:
> 1. Consistency. If this proposal is accepted, all other `case` statements
> will be able to take a `where` clause in the exact same position.
> 2. Expressiveness. In its new position, the `where` clause is actually in
> the middle—not at the end—of the case condition. This makes its role much
> more clear: `where` in a case condition is for refining the pattern to
> reject things which can't quite be expressed purely as a pattern. With
> `where` in this position, you will not be tempted to use it for a truly
> unrelated condition, as you might if `where` were after the initializer.
> You might be able to make an analogous argument for optional bindings,
> turning this:
>         optional-binding-head → "let" pattern initializer
> Into this:
>         optional-binding-head → "let" pattern where-clause? initializer
> With results like:
>         if let x where x > 5 = optionalX { … }
> I'm less convinced this is a good idea; there's no optional binding
> anywhere else in the language to be consistent with, the uses of a `where`
> clause are limited since an optional binding only captures one value
> anyway, and I don't think it makes much sense to complicate such a simple
> syntax.
> --
> Brent Royal-Gordon
> Architechies
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160610/20eaa235/attachment.html>

More information about the swift-evolution mailing list