[swift-evolution] Add a while clause to for loops

Xiaodi Wu xiaodi.wu at gmail.com
Wed Jun 8 13:40:03 CDT 2016


On Wed, Jun 8, 2016 at 1:24 PM, Tim Vermeulen <tvermeulen at me.com> wrote:

> > Why would breaking from a loop intuitively use a place analogy and
> continuing to the next iteration use a time analogy? This is totally made
> up; hence, it is not intuitive. I make no argument about whether or not it
> would be conceptually confusing. If you renamed 'break' to 'foo' and
> 'continue' to 'bar', it would not be intuitive, but you could likewise
> argue that it's not confusing, in that 'foo' is clearly not 'bar’.
>
> I think it’s quite intuitive, just like how a standard while loop is
> intuitive. “Execute this loop while this condition holds, for every case
> where that condition holds.” That’s how I would phrase such an expression
> in normal English. Doesn’t that make it intuitive? I can’t really switch
> the meanings of “while” and “where” and still have that sentence make sense.
>

That is not how your proposed construct reads. It actually reads: "for
every case where that condition holds while this condition holds." That is
a terrible sentence and not "normal" English.

> As I pointed out above with Tim's example, putting it all on one line is
> absolutely not 'neat'--it reads like spaghetti. That is one major beef I
> have with this proposal: that it *encourages* writing on one line too many
> things that, whether you use `where` or not, are much more clearly written
> on multiple lines. If writing everything on one line is for you the major
> advantage of this proposal, we could agree on everything else and I would
> be very much opposed to this proposal on that basis alone.
>
> You could argue that this proposal encourages writing a lot on a single
> line, but I could argue that not implementing this proposal would encourage
> people to write stuff like
>
> for number in fibonacci.lazy.filter({ number % 2 == 0 }).prefix(where: {
> $0 < 4_000_000 }) { }
>
> I would choose `for number in fibonacci where number % 2 == 0 while number
> < 4_000_000 { }` over the statement above any day. You can break up either
> into multiple lines for better readability, or you can move the conditions
> inside the loop, but that’s true no matter if this proposal will be
> accepted or rejected.
>

I'm writing in response to Haravikk's claim that method chaining encourages
putting things on multiple lines, while the proposed sugar encourages
putting things on one line. *If* you accept this premise, then I would
argue that it alone would be sufficient for me to be against the proposal.
It sounds like you don't agree with the premise, which is fine.


>
> > On Wed, Jun 8, 2016 at 3:38 AM, Haravikk<swift-evolution at haravikk.me
> (mailto:swift-evolution at haravikk.me)>wrote:
> > >
> > > > On 8 Jun 2016, at 01:54, Xiaodi Wu via swift-evolution<
> swift-evolution at swift.org(mailto:swift-evolution at swift.org)>wrote:
> > > >
> > > > 1) It is spelled out exactly what happens when a condition is met. I
> no longer have to remember whether the word that describes breaking from a
> loop uses a place analogy ("where") or a time analogy ("while" or "when”).
> > > >
> > > > (You cannot convince me that these words are intuitive when the
> meaning of "where" changes by context in today's Swift. Now, if you want to
> propose that these be named "breakif" and "continueif" instead, then I'd
> agree with you that they're intuitive names, but then they'd also be really
> ugly.)
> > > I’m not sure I agree that this is confusing,
> > Why would breaking from a loop intuitively use a place analogy and
> continuing to the next iteration use a time analogy? This is totally made
> up; hence, it is not intuitive. I make no argument about whether or not it
> would be conceptually confusing. If you renamed 'break' to 'foo' and
> 'continue' to 'bar', it would not be intuitive, but you could likewise
> argue that it's not confusing, in that 'foo' is clearly not 'bar'.
> >
> > > a little extra to learn for new programmers perhaps but I think it’s
> fairly intuitive:
> > >
> > > while let value = foo.next() where someCondition(value) { … }
> > >
> > > This reads to me as “repeat the following block until this fails to be
> true”, the conditional binding in this case fails to be true if
> someCondition(value) isn’t true, so the loop ends. I think the key thing
> here is that the where clause is for the conditional binding and not the
> loop itself, so in this respect it behaves exactly like an if or guard
> statement. Meanwhile:
> > >
> > > for eachValue in theValues where someCondition(eachValue) { … }
> > >
> > > Reads as “for everything in theValues do the following if
> someCondition(eachValue) is also true”, in other words this loop always
> tries to visit every element of the sequence (a while loop has no implicit
> awareness of the sequence, it’s really just an if statement that runs over
> and over). In this case the where clause is part of the loop itself. There
> may be an argument that where should be renamed on for loops to better
> distinguish this, but once you consider that there’s no pattern or
> conditional binding here I think it makes a reasonable amount of sense.
> > >
> > > Yes this could be handled by an if/guard statement with continue, and
> while as proposed here could be done with the same plus a break, but these
> things come up so often that it just makes a lot of sense to get it all
> neatly onto one line.
> > As I pointed out above with Tim's example, putting it all on one line is
> absolutely not 'neat'--it reads like spaghetti. That is one major beef I
> have with this proposal: that it *encourages* writing on one line too many
> things that, whether you use `where` or not, are much more clearly written
> on multiple lines. If writing everything on one line is for you the major
> advantage of this proposal, we could agree on everything else and I would
> be very much opposed to this proposal on that basis alone.
> >
> > > Chaining methods can do this, but it’s actually less readable IMO, or
> requires multiple lines to keep it clear which defeats the point.
> > >
> > >
> > For me, encouraging the use of multiple lines is the point. Tim's
> example demonstrated to me very clearly that clarity is not served by
> additional sugar to reduce the amount of punctuation on one line; it is
> served only by putting things on multiple lines. As I said above, I would
> cringe to read a loop that begins `for foo in bar where something while
> somethingElse where yetAnotherSomething while againAnotherSomething { ...
> }`.
> >
> > > As with where on if/guard statements it’s about keeping the simpler,
> more common cases as clean and readable as possible. If the re-use of the
> keyword where on the for loop is confusing then that’s an argument for
> renaming that, rather than rejecting while or ditching the whole thing IMO.
> Personally I think it’s okay, you just have to think what the where clause
> is actually acting upon.
> > >
> > > > 3) I have the flexibility to do something between the first if
> statement and the second if statement, if I want. By placing the break
> statement at the end of my loop, I could effectively choose to have one
> more iteration than if I placed it at the beginning of my loop. There is
> nothing you can do to mimic that choice with your proposed while clause,
> unless you want to also propose a `for...in...repeat { } while` syntax.
> > >
> > > So? Like where clauses this is for the simpler cases, if you want to
> do something more complex you remain free to use more complex conditionals.
> > And I was/am a proponent of SE-0099 to remove `where` from if and while
> loops; and if that succeeds I will definitely solicit comments to remove it
> from for loops!
> >
> > > A lot of the time you don’t need this however, so it makes sense to
> simplify the common case while leaving the complex one just as useful as it
> is today. Nothing about this proposal would stop you from using if/guard
> conditions inside the loop.
> > >
> > > > 4) This is the perhaps the important point. A beginning
> programmer--not any of us, presumably, but we were all beginners once--can
> accomplish everything that he or she desires without learning this new
> proposed syntax. Almost all texts, I believe, teach if statements before
> loops, and teach break and continue in the same breath as the loops
> themselves.
> > > In terms of teaching there shouldn’t be a problem with just teaching
> the basic building blocks first, then showing off simplifications later. As
> with any coding the most important thing is to get the intended behaviour
> correct, simplifying or optimising the code can always come later.
> > >
> > > You could argue the same thing about the shorthands around closures;
> I’m not sure why but I had trouble with those initially until after I’d
> worked with them in the more verbose form (with fully named parameters and
> a return statement) till I started to get the logic behind it, now I can
> just right a quick closure with the dollar sign shorthand.
> > Closures are--I'm sure you'd agree--a far more advanced concept than
> loops. Concepts like closing over a variable are very, very hard. Many
> useful things can be written without using closures. Not so many things
> could do without loops. It very much matters that a learner might feel that
> he or she cannot understand everything about a loop with the handwavy
> explanation that it'll "come later". One critique of using Java as a
> starting language is that you are forced to teach your students on day one
> that the real meaning of the words "public static void main(String[] args)"
> will "come later".
> >
> > >
> > > A good linter could be written to detect the presence of a simple
> if/guard right inside the loop and could then suggest the use of
> where/while as appropriate.
> >
> >
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160608/08ddc436/attachment.html>


More information about the swift-evolution mailing list