SE-0105: Removing Where Clauses from For-In Loops

Personally the logic seems pretty simple to me (especially the second and third one, plus the fourth isn't actually complex), I'd say the biggest problem to readability here is that the names seem too verbose, though without seeing the rest of the code that's hard to judge. For example the last example doesn't look so bad if you shorten the names like so:

   for colinearSegment in remainingSegments where colinearSegment.angle.isEssentially(angle: segment.angle) { // Is parameter name even necessary?

Basically on the basis that it's probably obvious from context that this is to do with lines that this is to do with lines, not sure if .isEssentially()'s parameter name can be changed, but I'm not sure why there needs to be a distinction that the angle is for an infinite line (an angle is an angle).

···

On 24 Jun 2016, at 22:33, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

most of these read as if there is too much logic stuffed into a single line:

for otherWall: Wall in self where otherWall != wall && !removedWalls.contains(otherWall) {

        for otherPieceOfFurnitureNode in localFurnitureModelUUIDsToInterfaceElements!.values where otherPieceOfFurnitureNode !== pieceOfFurnitureNode {

        for lineSegmentObject in wallRelatedLineSegments where remainingLineSegments.contains(lineSegmentObject) {

        for colinearLineSegmentObject in remainingLineSegments where colinearLineSegmentObject.angle.isEssentially(infiniteLineAngle: lineSegmentObject.angle) {

Just to clarify:

I was +1-ing real world `where` clauses. I am against this proposal.

So… -1 from me on this proposal (and SE-0099 for what it’s worth).

Sorry!

-t

(Thanks for pointing out the confusion my email may have caused, Goffredo)

···

On 28 Jun 2016, at 10:39, Tony Arnold <tony@thecocoabots.com> wrote:

I wasn’t going to be +1 guy, but “+1”:

I use where pretty heavily across both `if let` and in `for … in` loops.

I find both really readable when formatted, and I’d be disappointed to see them go.

I’m super annoyed that I missed (see “wasn’t paying attention during”) the review of SE-0099 because I would have loved to see `where` remain usable — it reads better than a comma and forces an order to things that made a lot of sense to me.

thanks,

Tony

On 27 Jun 2016, at 18:15, David Rönnqvist via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

We’ve also got two occurrences in our closed source, production code:

for (predicate, callback) in predicatesAndCallbacks where predicate(typedEvent) {
    callback(typedEvent)
}

and:

for conversation in conversations where conversation.state == .Established { }

They’re both quite simple and short, but I find them very readable (and I find the first one quite elegant). That said, it wouldn’t be much trouble for us to rewrite these using guard statements or any other construct.

- David

On 27 Jun 2016, at 00:47, Russ Bishop via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 23, 2016, at 7:14 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 23, 2016, at 7:34 PM, William Shipley via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I’m against removing “where" from “for/in”. I use it in my code and I think it aids readability quite a bit. In the example:

for x in theArray where x % 2 == 1 { print (x) }

I have used odd-even examples a lot when presenting this concept, and inevitably the response
is "Whoa, that's cool". What I'm missing are more challenging real-world use-cases to justify
the construct, and an exploration of why the challenging cases would not need debugger
support at that point.

My concern (and I am happy to be corrected) is that any code that becomes slightly more
complex loses the beauty and readability and hinders debugging at the same time.

— E

Here are two that are shipping right now.

for (key, tile) in self._cache where tile.tintColor != self.tintColor { }

for innerArray in actualValue where innerArray.contains(expectedElement) { }

Russ
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

----------
Tony Arnold
+61 411 268 532
http://thecocoabots.com/

ABN: 14831833541

----------
Tony Arnold
+61 411 268 532
http://thecocoabots.com/

ABN: 14831833541

I’ve occasionally thought something like that would be handy, but usually I find a way to reorganize it so it’s not necessary and it works just as well. Hard to say, really. Adding power might be good, but adding too much power might easily cross my own threshold of “too complex”.

I do think that proper consideration should be given to moving “where”. For example, here are a few of mine re-ordered:

for location where location.z == Global.cameraZ in path {
}

for below where contains(below) && hasSurfaceAt(below) in location.below.cardinals {
}

for neighbor where contains(neighbor) && isRampAt(neighbor) && !isFloorAt(neighbor.above) in location.cardinals {
}

To me that’s just as good and perhaps even better since it groups the name of the thing with the rules for the thing.

l8r
Sean

···

On Jun 24, 2016, at 10:10 AM, Charlie Monroe <charlie@charliemonroe.net> wrote:

If the `where` keyword were to stay in the language, how would you feel about extending it? One major argument is that it is not as powerful as guard or if. How about something like this was allowed:

for text in self.texts where let data = text.data(usingEncoding: NSASCIIEncoding) {
  /// Do something with data or text
}

On Jun 24, 2016, at 5:06 PM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

I’ll share some of mine from a single game project. Note this hasn’t been converted to Swift 3 and this is not all of them - just a varied sampling:

for location in random.sample(map, density: 0.007) where map.allowsGrassAt(location) && !map.hasGrassAt(location) {
}

for location in type.designatedLocations where location.z == Global.cameraZ && !locations.contains(location) {
}

for location in region where location.z == mouseLocation.z {
}

for location in path where location.z == Global.cameraZ {
}

for below in location.below.cardinals where contains(below) && hasSurfaceAt(below) {
}

for neighbor in location.cardinals where contains(neighbor) && isRampAt(neighbor) && !isFloorAt(neighbor.above) {
}

for neighbor in cardinals where contains(neighbor) && !isSolidAt(neighbor) {
}

for console in consoles.reverse() where console.hitTest(vector) {
}

And these 2 made good use, IMO, of “if-where” but I think that’s no longer in Swift 3? :/

if let there = debugClickedSurfaceAt, here = mouseSurface where Global.debugPathTest {
}

if let here = mouseAt where Global.debugWalkNeighbors {
}

l8r
Sean

On Jun 24, 2016, at 8:24 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Thank you for collecting and sharing these.

I suspect both of us look at these and say "Ah yes, this supports exactly what I've been saying".

-- E

On Jun 23, 2016, at 11:59 PM, William Shipley <wjs@mac.com> wrote:

Here are some of my real-world examples:

      for modelUUIDAndInterfaceElement in modelUUIDsToInterfaceElements where !usedInterfaceElements.contains(modelUUIDAndInterfaceElement.1) {

      }

      for anchor in wall.anchors where boundsRect.contains(anchor.origin) {

      }

      for otherWall: Wall in self where otherWall != wall && !removedWalls.contains(otherWall) {

      }

      for wall in self as Set<Wall> {
          for otherWall in self as Set<Wall> where otherWall != wall {

          }
      }

      for wall in self as Set<Wall> where !checkedWalls.contains(wall) {

      }

(x2 on that one)

      for otherPieceOfFurnitureNode in localFurnitureModelUUIDsToInterfaceElements!.values where otherPieceOfFurnitureNode !== pieceOfFurnitureNode {

      }

      for lineSegmentObject in wallRelatedLineSegments where remainingLineSegments.contains(lineSegmentObject) {

      }

      for colinearLineSegmentObject in remainingLineSegments where colinearLineSegmentObject.angle.isEssentially(infiniteLineAngle: lineSegmentObject.angle) {

      }

I think this is basically as many as are found on all of github?

-W

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Not a practitioner of 80-character line limits, I take it?

I don’t understand why anyone wouldn’t just let Xcode do the wrapping for most cases. I’ll add newlines if I think it adds to clarity, but in general I don’t want to code like i’m still on a Wyse WY-50.

Of course, to each their own style--I certainly wouldn't want Swift to force everyone to write lines of certain lengths. But 80-character lines is a common style, and I would say that a corollary of "to each their own" is that Swift's grammar should be usable and useful whether or not you adhere to such style choices.

I honestly don’t believe that this a common style in the Cocoa community. I’m not a member of the “old guard” having only come into this world 10 years ago with the iPhone, but just take a look at this delegate method in Objective-C:

- (void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error;

That’s well over 80 characters all by itself. This fits on my screen in a single line - and I work on a 15” MBP with room for my dock always visible on the side along with Xcode’s sidebar open! On a typical desktop-sized screen, 80-col lines must be comically short.

I don’t know why it should be assumed that people are adhering to a so-called standard that dates back to terminal screens that didn’t have color.

If the chief advantage of `where` is that it (quoting someone above) allows one to "understand as much as possible about the control flow of the loop from a single line of code," then we ought perhaps to question its appropriateness when the majority of its benefits [by which I mean, based on your examples and Sean's, more than half of the instances in which it is used] cannot be realized in a very common coding style.

Again, I dispute the idea (having no data but my own :P) that 80-col limits are common in this community.

l8r
Sean

···

On Jun 24, 2016, at 1:30 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:
On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Not a practitioner of 80-character line limits, I take it?

I don’t understand why anyone wouldn’t just let Xcode do the wrapping for most cases. I’ll add newlines if I think it adds to clarity, but in general I don’t want to code like i’m still on a Wyse WY-50.

Of course, to each their own style--I certainly wouldn't want Swift to force everyone to write lines of certain lengths.

The fact that you bring up a style in a proposal review [about a style imo] (and thus distracting the review process ) just reinforces the thinking that the proposal is about enforcing a particular style.

I think you made your point clearly in the discussions and proposal. Please allow other people to have their own opinions in this review :), otherwise it is not a review imo.

···

On Jun 24, 2016, at 11:30 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:

On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

But 80-character lines is a common style, and I would say that a corollary of "to each their own" is that Swift's grammar should be usable and useful whether or not you adhere to such style choices.

If the chief advantage of `where` is that it (quoting someone above) allows one to "understand as much as possible about the control flow of the loop from a single line of code," then we ought perhaps to question its appropriateness when the majority of its benefits [by which I mean, based on your examples and Sean's, more than half of the instances in which it is used] cannot be realized in a very common coding style.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

My terminology sucks because I don’t remember math terms but basically I’m trying to distinguish between angles of rays (0..<360º) and angles of lines (0..<180º). Because, like, if you have a line at 45º and another at 225º, well, they’re either collinear or parallel.

So I call the variants “rayAngle:” and “infiniteLineAngle:”. Not my finest hour.

-W

···

On Jun 24, 2016, at 3:00 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:
   for colinearSegment in remainingSegments where colinearSegment.angle.isEssentially(angle: segment.angle) { // Is parameter name even necessary?

Sorry, I wasn’t clear. I wasn’t saying that having it on the same exactly physical line is cleaner, I was saying that having the criteria for the “what I’m iterating” above the loop body and “what I’m doing with those things” inside the loop body is a much cleaner metaphor to me, and one of my favorite bits of Swift. It feels very Swifty to allow the programmer to separate these two concepts nicely.

I don’t care if/how lines are wrapped. In some cases I put the “where” on the next line in my code right now.

-Wil

···

On Jun 24, 2016, at 2:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

The point I was trying to bring up was that a purported advantage of keeping `where` is moot for those who *do* observe line limits, which includes the Swift stdlib itself as well as (IIUC) house style at Google, Microsoft, etc.

Not a practitioner of 80-character line limits, I take it?

I don’t understand why anyone wouldn’t just let Xcode do the wrapping for
most cases. I’ll add newlines if I think it adds to clarity, but in general
I don’t want to code like i’m still on a Wyse WY-50.

Of course, to each their own style--I certainly wouldn't want Swift to
force everyone to write lines of certain lengths. But 80-character lines is
a common style, and I would say that a corollary of "to each their own" is
that Swift's grammar should be usable and useful whether or not you adhere
to such style choices.

If the chief advantage of `where` is that it (quoting someone above)
allows one to "understand as much as possible about the control flow of
the loop from a single line of code," then we ought perhaps to question its
appropriateness when the majority of its benefits [by which I mean, based
on your examples and Sean's, more than half of the instances in which it is
used] cannot be realized in a very common coding style.

IMO, we shouldn't be talking about "a single line of code" so much as "a
single cohesive construct". What's important to me isn't the line length or
whether the "where" part has to wrap onto another line, it's the number of
potentially divergent constructs I have to parse mentally in order to
determine the meaning of the loop.

With "for-in-where", it's three:

    for item(1) in someCollection(2) where someCondition(3)

With the alternatives suggested using if/guard/continue/break, it's more
than that:

    for item(1) in someCollection(2) {
        [if | guard...else](3) someCondition(4) {
            [continue | break](5)
        }
    }

I have to be more careful now interpreting the meaning of this loop because
both or either of if/guard or continue/break can invert its meaning, where
was "for-in-where" is concise and clear.

Doing .lazy.filter{...} is slightly cleaner than this, but still suffers
from the disadvantage that it's very easy for newcomers to leave out the
"lazy" part and accidentally write poorly performing code, and to the
argument that "where" is considered confusing by some users, I would argue
that it's easier to explain how it works than why "lazy" is necessary in
this context.

···

On Fri, Jun 24, 2016 at 11:30 AM Xiaodi Wu via swift-evolution < swift-evolution@swift.org> wrote:

On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:

On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Sorry, I think I got a bit side-tracked, didn't mean to seem too critical of the name choice, my point was that the logic is actually pretty straightforward, and the line is long because of the verbose naming rather than the presence of a where clause (which could also be moved to another line as another option). As always you should use whatever names help you to understand and remember the intent of the code best, meanwhile I should actually focus on what my point was supposed to be =D

So yeah, I don't think any of the examples presented have had "too much logic" for a where clause, while more complex cases with ands, ors, etc. might become a bit less immediately readable, it's no more so than any other if-condition, and it's an issue of personal style choice regardless, rather than a fault with a where clause.

···

On 24 Jun 2016, at 23:38, William Jon Shipley <wjs@delicious-monster.com> wrote:

On Jun 24, 2016, at 3:00 PM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
   for colinearSegment in remainingSegments where colinearSegment.angle.isEssentially(angle: segment.angle) { // Is parameter name even necessary?

My terminology sucks because I don’t remember math terms but basically I’m trying to distinguish between angles of rays (0..<360º) and angles of lines (0..<180º). Because, like, if you have a line at 45º and another at 225º, well, they’re either collinear or parallel.

So I call the variants “rayAngle:” and “infiniteLineAngle:”. Not my finest hour.

If the `where` keyword were to stay in the language, how would you feel about extending it? One major argument is that it is not as powerful as guard or if. How about something like this was allowed:

for text in self.texts where let data = text.data(usingEncoding: NSASCIIEncoding) {
  /// Do something with data or text
}

I noticed this in some code I was writing just now and came to mention it.

Right now I’ve got this (Note: tagsForGroup is [String?]):

for (index, range) in zip(groupRanges.indices, groupRanges) where tagsForGroup[index] != nil {

  let tagForGroup = tagsForGroup[index]!
  // tag `range` with `tagForGroup`
}

It would be nicer to write it like this:

for (index, range) in zip(groupRanges.indices, groupRanges) where let tag = tagsForGroup[index] {

  // tag `range` with `tag`
}

I could do it with a guard, but as somebody so eloquently put, it produces more divergent constructs for readers. It’s part of a complex regex matching and processing workflow, so I want to keep it readable and make it explicit that we’re only tagging/processing groups where a tag is defined.

Karl

···

On 24 Jun 2016, at 17:10, Charlie Monroe via swift-evolution <swift-evolution@swift.org> wrote:

Not a practitioner of 80-character line limits, I take it?

I don’t understand why anyone wouldn’t just let Xcode do the wrapping
for most cases. I’ll add newlines if I think it adds to clarity, but in
general I don’t want to code like i’m still on a Wyse WY-50.

Of course, to each their own style--I certainly wouldn't want Swift to
force everyone to write lines of certain lengths. But 80-character lines is
a common style, and I would say that a corollary of "to each their own" is
that Swift's grammar should be usable and useful whether or not you adhere
to such style choices.

If the chief advantage of `where` is that it (quoting someone above)
allows one to "understand as much as possible about the control flow of
the loop from a single line of code," then we ought perhaps to question its
appropriateness when the majority of its benefits [by which I mean, based
on your examples and Sean's, more than half of the instances in which it is
used] cannot be realized in a very common coding style.

IMO, we shouldn't be talking about "a single line of code" so much as "a
single cohesive construct". What's important to me isn't the line length or
whether the "where" part has to wrap onto another line, it's the number of
potentially divergent constructs I have to parse mentally in order to
determine the meaning of the loop.

With "for-in-where", it's three:

    for item(1) in someCollection(2) where someCondition(3)

With the alternatives suggested using if/guard/continue/break, it's more
than that:

    for item(1) in someCollection(2) {
        [if | guard...else](3) someCondition(4) {
            [continue | break](5)
        }
    }

I have to be more careful now interpreting the meaning of this loop
because both or either of if/guard or continue/break can invert its
meaning, where was "for-in-where" is concise and clear.

And if `while` is added along with `where`, all this goes out the window.

Doing .lazy.filter{...} is slightly cleaner than this, but still suffers
from the disadvantage that it's very easy for newcomers to leave out the
"lazy" part and accidentally write poorly performing code, and to the
argument that "where" is considered confusing by some users, I would argue
that it's easier to explain how it works than why "lazy" is necessary in
this context.

Clearly, eagerly filtering results in slower code, but based on the
examples provided above I don't imagine any of them would turn into "poorly
performing" code with eager filtering. In fact, I see some that could run a
little faster with some refactoring along these lines. In any case,
optimizing performance comes after correctness; a user who can't grasp
`lazy` can nonetheless still write useful, correct code.

···

On Fri, Jun 24, 2016 at 1:38 PM, Tony Allevato <allevato@google.com> wrote:

On Fri, Jun 24, 2016 at 11:30 AM Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:

On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

_______________________________________________

swift-evolution mailing list

swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

>
>>
>> Not a practitioner of 80-character line limits, I take it?
>
> I don’t understand why anyone wouldn’t just let Xcode do the wrapping
for most cases. I’ll add newlines if I think it adds to clarity, but in
general I don’t want to code like i’m still on a Wyse WY-50.
>
> Of course, to each their own style--I certainly wouldn't want Swift to
force everyone to write lines of certain lengths. But 80-character lines is
a common style, and I would say that a corollary of "to each their own" is
that Swift's grammar should be usable and useful whether or not you adhere
to such style choices.

I honestly don’t believe that this a common style in the Cocoa community.

We're talking about the Swift community here, and Swift stdlib would be a
good starting point as to what is a common or at least accepted style; it
uses 80-character lines.

···

On Fri, Jun 24, 2016 at 1:56 PM, Sean Heber <sean@fifthace.com> wrote:

> On Jun 24, 2016, at 1:30 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:
> On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:
> On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I’m not a member of the “old guard” having only come into this world 10
years ago with the iPhone, but just take a look at this delegate method in
Objective-C:

- (void)locationManager:(CLLocationManager *)manager
rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError
*)error;

That’s well over 80 characters all by itself. This fits on my screen in a
single line - and I work on a 15” MBP with room for my dock always visible
on the side along with Xcode’s sidebar open! On a typical desktop-sized
screen, 80-col lines must be comically short.

I don’t know why it should be assumed that people are adhering to a
so-called standard that dates back to terminal screens that didn’t have
color.

> If the chief advantage of `where` is that it (quoting someone above)
allows one to "understand as much as possible about the control flow of the
loop from a single line of code," then we ought perhaps to question its
appropriateness when the majority of its benefits [by which I mean, based
on your examples and Sean's, more than half of the instances in which it is
used] cannot be realized in a very common coding style.

Again, I dispute the idea (having no data but my own :P) that 80-col
limits are common in this community.

l8r
Sean

Not a practitioner of 80-character line limits, I take it?

I don’t understand why anyone wouldn’t just let Xcode do the wrapping
for most cases. I’ll add newlines if I think it adds to clarity, but in
general I don’t want to code like i’m still on a Wyse WY-50.

Of course, to each their own style--I certainly wouldn't want Swift to
force everyone to write lines of certain lengths. But 80-character lines is
a common style, and I would say that a corollary of "to each their own" is
that Swift's grammar should be usable and useful whether or not you adhere
to such style choices.

If the chief advantage of `where` is that it (quoting someone above)
allows one to "understand as much as possible about the control flow of
the loop from a single line of code," then we ought perhaps to question its
appropriateness when the majority of its benefits [by which I mean, based
on your examples and Sean's, more than half of the instances in which it is
used] cannot be realized in a very common coding style.

IMO, we shouldn't be talking about "a single line of code" so much as "a
single cohesive construct". What's important to me isn't the line length or
whether the "where" part has to wrap onto another line, it's the number of
potentially divergent constructs I have to parse mentally in order to
determine the meaning of the loop.

With "for-in-where", it's three:

    for item(1) in someCollection(2) where someCondition(3)

With the alternatives suggested using if/guard/continue/break, it's more
than that:

    for item(1) in someCollection(2) {
        [if | guard...else](3) someCondition(4) {
            [continue | break](5)
        }
    }

I have to be more careful now interpreting the meaning of this loop
because both or either of if/guard or continue/break can invert its
meaning, where was "for-in-where" is concise and clear.

I like this way of thinking a lot, actually. Number of divergent constructs
you have to parse. Here's the thing: I think it supports removal, not
retaining. Here's why:

For every loop you encounter, to understand its meaning you *must* look for
`break` and `continue` statements, and when they're inside `if` and `guard`
you must consider how the condition is evaluated. This is a given, a sunk
cost; I see no way they can be prohibited from the language, so these are
all things you will have to look for and mentally parse in order to
understand the behavior of a loop.

Now, if you add `where`, then that is one additional divergent construct
you must understand and parse. And moreover, since you know it exists, to
be sure you really understand what's going on you'll have to check the end
of every `for...in` statement to see if it's there. And in case the line
doesn't fit on your screen, you'll have to try scrolling to see if there's
more (or read on to the next line if you've turned on line wrapping). And
you'll have to do this for *every* `for...in` loop, where the majority
don't use `where` at all!

So, I agree with you, what's important to me as well is number of divergent
constructs I have to parse. But with the removal of `where`, the number of
divergent constructs I have to think about while reading Swift loops will
decrease, not increase.

Doing .lazy.filter{...} is slightly cleaner than this, but still suffers

···

On Fri, Jun 24, 2016 at 1:38 PM, Tony Allevato <allevato@google.com> wrote:

On Fri, Jun 24, 2016 at 11:30 AM Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:

On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

from the disadvantage that it's very easy for newcomers to leave out the
"lazy" part and accidentally write poorly performing code, and to the
argument that "where" is considered confusing by some users, I would argue
that it's easier to explain how it works than why "lazy" is necessary in
this context.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Not a practitioner of 80-character line limits, I take it?

I don’t understand why anyone wouldn’t just let Xcode do the wrapping for
most cases. I’ll add newlines if I think it adds to clarity, but in general
I don’t want to code like i’m still on a Wyse WY-50.

Of course, to each their own style--I certainly wouldn't want Swift to
force everyone to write lines of certain lengths.

The fact that you bring up a style in a proposal review [about a style
imo] (and thus distracting the review process ) just reinforces the
thinking that the proposal is about enforcing a particular style.

On the contrary, new data have been presented on how `where` is being used.
These raise a point that `where` promotes a particular style over others,
and what I'm trying to point out here--not mentioned previously--is that
one purported major benefit of `where` (putting everything on one line) is
inapplicable to the Swift stdlib's own style as well as those of others. It
is not a distraction to tackle new points that are brought up during the
review process.

I think you made your point clearly in the discussions and proposal.
Please allow other people to have their own opinions in this review :),
otherwise it is not a review imo.

You may note that I've confined my comments to particulars raised by
others' comments. And, FWIW, I haven't actually reviewed the proposal, so
I'm not sure how you know how I feel about it.

···

On Fri, Jun 24, 2016 at 4:04 PM, Jose Cheyo Jimenez <cheyo@masters3d.com> wrote:

On Jun 24, 2016, at 11:30 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:
On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:

On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

But 80-character lines is a common style, and I would say that a corollary
of "to each their own" is that Swift's grammar should be usable and useful
whether or not you adhere to such style choices.

If the chief advantage of `where` is that it (quoting someone above)
allows one to "understand as much as possible about the control flow of
the loop from a single line of code," then we ought perhaps to question its
appropriateness when the majority of its benefits [by which I mean, based
on your examples and Sean's, more than half of the instances in which it is
used] cannot be realized in a very common coding style.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Thanks for the great way of breaking it down. The issue I see is that it is quite easy to incorrectly assume what (3) and (5) are below. Some assume it breaks, others that it just skips and continues.

So in my mind there’s nothing wrong with wanting something that can be written on one line together with the `for in`. The problem is this particular syntax is ambiguous.

Patrick

···

On 25 Jun 2016, at 4:38 AM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

IMO, we shouldn't be talking about "a single line of code" so much as "a single cohesive construct". What's important to me isn't the line length or whether the "where" part has to wrap onto another line, it's the number of potentially divergent constructs I have to parse mentally in order to determine the meaning of the loop.

With "for-in-where", it's three:

    for item(1) in someCollection(2) where someCondition(3)

With the alternatives suggested using if/guard/continue/break, it's more than that:

    for item(1) in someCollection(2) {
        [if | guard...else](3) someCondition(4) {
            [continue | break](5)
        }
    }

I have to be more careful now interpreting the meaning of this loop because both or either of if/guard or continue/break can invert its meaning, where was "for-in-where" is concise and clear.

Doing .lazy.filter{...} is slightly cleaner than this, but still suffers from the disadvantage that it's very easy for newcomers to leave out the "lazy" part and accidentally write poorly performing code, and to the argument that "where" is considered confusing by some users, I would argue that it's easier to explain how it works than why "lazy" is necessary in this context.

I think this is an excellent argument for keeping where — I was tempted to make a hand waving argument in favor of keeping where, but I think you made the case as well as it can be made. (I suppose you could even argue that there are really 7 components to the other construct since you can have continue, break, or return, but that just underscores your point.)

I also agree with your points about using lazy.filter instead.

BTW, the project I’m currently working on has about 10-15 for loops that use where.

Net/net: I’m a -1 on the proposal.

···

On Jun 24, 2016, at 11:38 AM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

IMO, we shouldn't be talking about "a single line of code" so much as "a single cohesive construct". What's important to me isn't the line length or whether the "where" part has to wrap onto another line, it's the number of potentially divergent constructs I have to parse mentally in order to determine the meaning of the loop.

With "for-in-where", it's three:

    for item(1) in someCollection(2) where someCondition(3)

With the alternatives suggested using if/guard/continue/break, it's more than that:

    for item(1) in someCollection(2) {
        [if | guard...else](3) someCondition(4) {
            [continue | break](5)
        }
    }

I have to be more careful now interpreting the meaning of this loop because both or either of if/guard or continue/break can invert its meaning, where was "for-in-where" is concise and clear.

Doing .lazy.filter{...} is slightly cleaner than this, but still suffers from the disadvantage that it's very easy for newcomers to leave out the "lazy" part and accidentally write poorly performing code, and to the argument that "where" is considered confusing by some users, I would argue that it's easier to explain how it works than why "lazy" is necessary in this context.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

>
>>
>> Not a practitioner of 80-character line limits, I take it?
>
> I don’t understand why anyone wouldn’t just let Xcode do the wrapping for most cases. I’ll add newlines if I think it adds to clarity, but in general I don’t want to code like i’m still on a Wyse WY-50.
>
> Of course, to each their own style--I certainly wouldn't want Swift to force everyone to write lines of certain lengths. But 80-character lines is a common style, and I would say that a corollary of "to each their own" is that Swift's grammar should be usable and useful whether or not you adhere to such style choices.

I honestly don’t believe that this a common style in the Cocoa community.

We're talking about the Swift community here, and Swift stdlib would be a good starting point as to what is a common or at least accepted style; it uses 80-character lines.

While it does, it makes sense only for readability purposes of the documentation. For example, I see absolute no reason why to split https://github.com/apple/swift/blob/master/stdlib/public/core/StringBuffer.swift#L233 into two lines.

It makes the code less readable.

80-char style made sense in C, where everything is pretty much top-level. But given that you declare a class, within which you declare another class, within which you declare methods, the first level of the method indentation is at level 3, which given 4 spaces per tab gives you 12 characters already. Adding a few levels (for-cycle + an if statement within the for cycle) gives you 20 characters of just whitespace (1/4 of the allocated 80 chars per line).

Which is why I don't believe this code style is valid in a modern language. My personal guess is that it should be upped to e.g. 160 chars per line - that kind of makes sense. There is no particular reason other than historic why we're still using 80 chars per line.

···

On Jun 24, 2016, at 9:00 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
On Fri, Jun 24, 2016 at 1:56 PM, Sean Heber <sean@fifthace.com <mailto:sean@fifthace.com>> wrote:
> On Jun 24, 2016, at 1:30 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com <mailto:wjs@mac.com>> wrote:
> On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

I’m not a member of the “old guard” having only come into this world 10 years ago with the iPhone, but just take a look at this delegate method in Objective-C:

- (void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error;

That’s well over 80 characters all by itself. This fits on my screen in a single line - and I work on a 15” MBP with room for my dock always visible on the side along with Xcode’s sidebar open! On a typical desktop-sized screen, 80-col lines must be comically short.

I don’t know why it should be assumed that people are adhering to a so-called standard that dates back to terminal screens that didn’t have color.

> If the chief advantage of `where` is that it (quoting someone above) allows one to "understand as much as possible about the control flow of the loop from a single line of code," then we ought perhaps to question its appropriateness when the majority of its benefits [by which I mean, based on your examples and Sean's, more than half of the instances in which it is used] cannot be realized in a very common coding style.

Again, I dispute the idea (having no data but my own :P) that 80-col limits are common in this community.

l8r
Sean

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

[...] what I'm trying to point out here--not mentioned previously--is that one purported major benefit of `where` (putting everything on one line) is inapplicable to the Swift stdlib's own style as well as those of others.

That's like saying that you can't use long method names imported from ObjC in Swift. Why can't you use

for anchor
  in wall.anchors
  where boundsRect.contains(anchor.origin)

or similar, if you need to fit within the 80 chars - just like you'd do with a compound if statement that exceeds 80 chars.

The major benefit isn't saving a line (though it's 3 unless you're willing to add { continue } on the same line), but to express your intend to filter the array right within the for-in statement.

When you look around someone else's code, you immediately see that the person is only going through anchors without bounds without the need to examine the loop's body, which may be collapsed (hidden) by the editor.

···

On Jun 24, 2016, at 11:14 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

I think you made your point clearly in the discussions and proposal. Please allow other people to have their own opinions in this review :), otherwise it is not a review imo.

You may note that I've confined my comments to particulars raised by others' comments. And, FWIW, I haven't actually reviewed the proposal, so I'm not sure how you know how I feel about it.

But 80-character lines is a common style, and I would say that a corollary of "to each their own" is that Swift's grammar should be usable and useful whether or not you adhere to such style choices.

If the chief advantage of `where` is that it (quoting someone above) allows one to "understand as much as possible about the control flow of the loop from a single line of code," then we ought perhaps to question its appropriateness when the majority of its benefits [by which I mean, based on your examples and Sean's, more than half of the instances in which it is used] cannot be realized in a very common coding style.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

>
>>
>> Not a practitioner of 80-character line limits, I take it?
>
> I don’t understand why anyone wouldn’t just let Xcode do the wrapping
for most cases. I’ll add newlines if I think it adds to clarity, but in
general I don’t want to code like i’m still on a Wyse WY-50.
>
> Of course, to each their own style--I certainly wouldn't want Swift to
force everyone to write lines of certain lengths. But 80-character lines is
a common style, and I would say that a corollary of "to each their own" is
that Swift's grammar should be usable and useful whether or not you adhere
to such style choices.

I honestly don’t believe that this a common style in the Cocoa community.

We're talking about the Swift community here, and Swift stdlib would be a
good starting point as to what is a common or at least accepted style; it
uses 80-character lines.

While it does, it makes sense only for readability purposes of the
documentation. For example, I see absolute no reason why to split
https://github.com/apple/swift/blob/master/stdlib/public/core/StringBuffer.swift#L233 into
two lines.

It makes the code less readable.

80-char style made sense in C, where everything is pretty much top-level.
But given that you declare a class, within which you declare another class,
within which you declare methods, the first level of the method indentation
is at level 3, which given 4 spaces per tab gives you 12 characters
already. Adding a few levels (for-cycle + an if statement within the for
cycle) gives you 20 characters of just whitespace (1/4 of the allocated 80
chars per line).

Which is why I don't believe this code style is valid in a modern language.

This is one style that some very intelligent people use in Swift. I'm not
going to debate what styles are "valid."

My personal guess is that it should be upped to e.g. 160 chars per line -

···

On Fri, Jun 24, 2016 at 2:26 PM, Charlie Monroe <charlie@charliemonroe.net> wrote:

On Jun 24, 2016, at 9:00 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:
On Fri, Jun 24, 2016 at 1:56 PM, Sean Heber <sean@fifthace.com> wrote:

> On Jun 24, 2016, at 1:30 PM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:
> On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com> wrote:
> On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

that kind of makes sense. There is no particular reason other than historic
why we're still using 80 chars per line.

I’m not a member of the “old guard” having only come into this world 10
years ago with the iPhone, but just take a look at this delegate method in
Objective-C:

- (void)locationManager:(CLLocationManager *)manager
rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError
*)error;

That’s well over 80 characters all by itself. This fits on my screen in a
single line - and I work on a 15” MBP with room for my dock always visible
on the side along with Xcode’s sidebar open! On a typical desktop-sized
screen, 80-col lines must be comically short.

I don’t know why it should be assumed that people are adhering to a
so-called standard that dates back to terminal screens that didn’t have
color.

> If the chief advantage of `where` is that it (quoting someone above)
allows one to "understand as much as possible about the control flow of the
loop from a single line of code," then we ought perhaps to question its
appropriateness when the majority of its benefits [by which I mean, based
on your examples and Sean's, more than half of the instances in which it is
used] cannot be realized in a very common coding style.

Again, I dispute the idea (having no data but my own :P) that 80-col
limits are common in this community.

l8r
Sean

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

>
>>
>> Not a practitioner of 80-character line limits, I take it?
>
> I don’t understand why anyone wouldn’t just let Xcode do the wrapping for most cases. I’ll add newlines if I think it adds to clarity, but in general I don’t want to code like i’m still on a Wyse WY-50.
>
> Of course, to each their own style--I certainly wouldn't want Swift to force everyone to write lines of certain lengths. But 80-character lines is a common style, and I would say that a corollary of "to each their own" is that Swift's grammar should be usable and useful whether or not you adhere to such style choices.

I honestly don’t believe that this a common style in the Cocoa community.

We're talking about the Swift community here, and Swift stdlib would be a good starting point as to what is a common or at least accepted style; it uses 80-character lines.

While it does, it makes sense only for readability purposes of the documentation. For example, I see absolute no reason why to split https://github.com/apple/swift/blob/master/stdlib/public/core/StringBuffer.swift#L233 into two lines.

It makes the code less readable.

80-char style made sense in C, where everything is pretty much top-level. But given that you declare a class, within which you declare another class, within which you declare methods, the first level of the method indentation is at level 3, which given 4 spaces per tab gives you 12 characters already. Adding a few levels (for-cycle + an if statement within the for cycle) gives you 20 characters of just whitespace (1/4 of the allocated 80 chars per line).

Which is why I don't believe this code style is valid in a modern language.

This is one style that some very intelligent people use in Swift. I'm not going to debate what styles are "valid."

I'm sorry, if this sounded offensive in any way, I certainly did not mean it that way, I simply wanted to point out why I believe the 80-char limit is a bit limiting nowadays given that you can nest various constructs.

···

On Jun 24, 2016, at 9:33 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Fri, Jun 24, 2016 at 2:26 PM, Charlie Monroe <charlie@charliemonroe.net <mailto:charlie@charliemonroe.net>> wrote:

On Jun 24, 2016, at 9:00 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Fri, Jun 24, 2016 at 1:56 PM, Sean Heber <sean@fifthace.com <mailto:sean@fifthace.com>> wrote:
> On Jun 24, 2016, at 1:30 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> On Fri, Jun 24, 2016 at 6:37 AM, William Shipley <wjs@mac.com <mailto:wjs@mac.com>> wrote:
> On Jun 23, 2016, at 11:04 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

My personal guess is that it should be upped to e.g. 160 chars per line - that kind of makes sense. There is no particular reason other than historic why we're still using 80 chars per line.

I’m not a member of the “old guard” having only come into this world 10 years ago with the iPhone, but just take a look at this delegate method in Objective-C:

- (void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error;

That’s well over 80 characters all by itself. This fits on my screen in a single line - and I work on a 15” MBP with room for my dock always visible on the side along with Xcode’s sidebar open! On a typical desktop-sized screen, 80-col lines must be comically short.

I don’t know why it should be assumed that people are adhering to a so-called standard that dates back to terminal screens that didn’t have color.

> If the chief advantage of `where` is that it (quoting someone above) allows one to "understand as much as possible about the control flow of the loop from a single line of code," then we ought perhaps to question its appropriateness when the majority of its benefits [by which I mean, based on your examples and Sean's, more than half of the instances in which it is used] cannot be realized in a very common coding style.

Again, I dispute the idea (having no data but my own :P) that 80-col limits are common in this community.

l8r
Sean

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution