> On Jun 9, 2016, at 6:54 PM, Jordan Rose <[email protected]> wrote: > > >> On Jun 8, 2016, at 22:19, Charlie Monroe via swift-evolution >> <[email protected] <mailto:[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 >
See my latest post - included results with -Ofast. But still, using filter and lazy.filter is 10+% slower, which were the suggested alternatives to `where`.
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
