[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