<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jun 10, 2016 at 2:10 PM, Brent Royal-Gordon via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">> Unlike in switch statements and do loops, a for-in loop's where-clause is separated from the pattern it modifies.<br>
<br>
</span>(I think "do loops" is supposed to be "do-catch statements"?)<br>
<span class=""><br>
> for case? pattern in expression where-clause? code-block<br>
><br>
> case-item-list → pattern where-clause? | pattern where-clause? , case-item-list<br>
><br>
> catch pattern? where-clause? code-block<br>
><br>
> 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.<br>
<br>
</span>I'm definitely in favor of this. (I should be—I'm listed as coauthor.)<br>
<br>
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.<br>
<br>
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:<br>
<br>
case .foo, .bar where baz():<br>
<br>
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.<br>
<br>
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.<br>
<span class=""><br>
> Note where clauses in case conditions and optional bindings have been removed in SE-0099.<br>
<br>
</span>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:<br>
<br>
case-condition → "case" pattern initializer<br>
<br>
We would change it to:<br>
<br>
case-condition → "case" pattern where-clause? initializer<br>
<br>
In use, this would look like:<br>
<br>
if case .some(let Point.cartesian(x, y)) where x < y = json["rect"]?["origin"].flatMap(.init(rawValue:)) { … }<br></blockquote><div><br></div><div>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.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Of course, the above could equally be written without a `where` clause:<br>
<br>
if case .some(let Point.cartesian(x, y)) = json["rect"]?["origin"].flatMap(.init(rawValue:)), x < y { … }<br>
<br>
But nevertheless, I think it's a good idea. Why? Two reasons:<br>
<br>
1. Consistency. If this proposal is accepted, all other `case` statements will be able to take a `where` clause in the exact same position.<br>
<br>
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.<br>
<br>
You might be able to make an analogous argument for optional bindings, turning this:<br>
<br>
optional-binding-head → "let" pattern initializer<br>
<br>
Into this:<br>
<br>
optional-binding-head → "let" pattern where-clause? initializer<br>
<br>
With results like:<br>
<br>
if let x where x > 5 = optionalX { … }<br>
<br>
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.<br>
<div class="HOEnZb"><div class="h5"><br>
--<br>
Brent Royal-Gordon<br>
Architechies<br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br></div></div>