> On Jun 8, 2016, at 22:19, Charlie Monroe via swift-evolution 
> <[email protected]> wrote:
> 
>> 
>> On Jun 9, 2016, at 5:51 AM, Erica Sadun via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> 
>>> On Jun 8, 2016, at 9:36 PM, Brent Royal-Gordon <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>>> Upon accepting SE-0099, the core team is removing `where` clauses from 
>>>> condition clauses, writing "the 'where' keyword can be retired from its 
>>>> purpose as a boolean condition introducer." 
>>>> 
>>>> Inspiried by Xiaodi Wu, I now propose removing `where` clauses from `for 
>>>> in` loops, where they are better expressed (and read) as guard conditions. 
>>> 
>>> Do you propose to remove `for case` as well? That can equally be handled by 
>>> a `guard case` in the loop body.
>>> 
>>> Alternate proposal: Move `where` clauses to be adjacent to the 
>>> pattern—rather than the sequence expression—in a `for` loop, just as they 
>>> are in these other syntaxes.
>>> 
>>>     for n where n.isOdd in 1...1_000 { … }
>>> 
>>> This makes them more consistent with the syntax in `switch` cases and 
>>> `catch` statements, while also IMHO clarifying the role of the `where` 
>>> clause as a filter on the elements seen by the loop.
>> 
>> I saw your post on that *after* I finished sending this. Moving `where` next 
>> to the pattern, like you'd find in `catch` and switch `case`, the code would 
>> look like this:
>> 
>> for i where i % 2 == 0 in sequence {
>>     // do stuff
>> }
>> 
>> I agree that's really clever and an improvement but after coming up with all 
>> the points about wrong expectations about termination vs filtering, the 
>> better use of guard, and fetishes about vertical compactness, I think (call 
>> it +0.6) I'm going to stick to my guns on this one - and for `for case` too. 
>> I've been wuxxed.
>> 
>> * New users might expect the sequence to terminate as soon as i % 2 is 1, 
>> rather than the correct interpretation which is "this is a filtering 
>> operation"
>> * The code can be expressed less ambiguously as 
>> 
>> for i in sequence.filter({ return i % 2 == 0 }) {
>>     // do stuff
>> }
> 
> It's important to keep in mind that .filter without using .lazy copies the 
> array. So you need to keep using sequence.lazy.filter({ return i %2 == 0 }), 
> unless you're OK with giving up some performance, which a) adds boilerplate, 
> b) not many people will remember to do.
> 
> I've taken the time to run a test, going through milion numbers (several 
> times) using:
> 
> for i in arr { if i % 2 == 0 { continue } }
> for i in arr where i % 2 == 0 { }
> for i in arr.filter({ $0 % 2 == 0 }) { }
> for i in arr.lazy.filter({ $0 % 2 == 0 }) { }
> 
> Results:
> 
> - plain for loop with if-continue: 27.19 seconds (+1.76%)
> - with where: 26.72 seconds (+0.00%)
> - .filter: 44.73 seconds (+67.40%)
> - .lazy.filter: 31.66 seconds (+18.48%)
> 
> Yes, 100 milion numbers is an extreme, but it demonstrates that any of the 
> suggested expressions will be slower, mainly if the caller doesn't use .lazy 
> (67% !!!). The only comparable solution is adding additional lines of code 
> into the body of the for loop by adding an if statement.

Just to double-check, was this with optimizations on? Because -Onone numbers 
aren’t nearly as motivating, but I would expect -O to remove the loop entirely 
in the simple case.

Jordan

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to