> 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
