Add a while clause to for loops

+1 as well

Thanks!

Jamie

On 6/7/16, 7:20 AM, "swift-evolution-bounces@swift.org on behalf of
Vladimir.S via swift-evolution" <swift-evolution-bounces@swift.org on

···

behalf of swift-evolution@swift.org> wrote:

My +1 to the proposal and for Charlie's opinion. I believe `while` in
`for`
loop would be very handy and helpful in some situations, it is a pair for
existed `where`, its meaning is obvious, and its existence can't depend
on
existence of any method in collections. I'd like to see a formal proposal
for this feature.

On 07.06.2016 8:18, Charlie Monroe via swift-evolution wrote:

I strongly disagree.

Exchanging

for result in results where result.value != .Warning while result.value
!=
.Error {
/// ...
}

for either

for result in results.filter({ $0.value != .Warning }).prefix(while: {
$0.value != .Error })) {
/// ...
}

or

for result in results {
if result.value == .Warning { continue }
if result.value == .Error { break }

/// ...
}

Seems like an absolute step back. Not to mention filter(_:) doesn't
return
a lazy collection, but will recreate it, while the `where` will do
on-the-fly check.

On Jun 7, 2016, at 1:34 AM, Xiaodi Wu via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Personally, given this discussion and the one about `where` in if and
while statements, I would not be opposed to elimination of `where` in
control statements altogether.

My reasoning would be that words like filter and prefix unambiguously
indicate what happens to elements of a sequence for which the predicate
returns false, whereas words like where and while are ambiguous.

On Mon, Jun 6, 2016 at 17:52 Tim Vermeulen <tvermeulen@me.com >>> <mailto:tvermeulen@me.com>> wrote:

    I didn¹t mean we should really get rid of the `where` clause, it¹s
    great. I guess the point I was trying to make is that we can use a
    `where` clause with a `for` loop in Swift, despite the existence of
    the `filter` method. So despite `prefix(while:)` in Swift 3, there
    might be room for a `while` clause. I think it makes the code a lot
    more readable, much like how `where` can make a `for` loop a lot
more
    readable than using `filter`.

    > The burden of proof for adding new features is different from
that
    for taking away existing features.
    >
    > If a feature doesn't yet exist, a successful proposal will show
how
    it provides additional and non-trivial utility. If a feature
already
    exists, a successful proposal to remove it will show how it is
    harmful to the language or contrary to the direction in which it is
    evolving.
    >
    > On Mon, Jun 6, 2016 at 15:38 Tim Vermeulen<tvermeulen@me.com >>> <mailto:tvermeulen@me.com>(mailto:tvermeulen@me.com >>> <mailto:tvermeulen@me.com>)>wrote:
    > > The functionality of the `where` clause in `for` loops also
    already can be mimicked using `filter`. Wouldn¹t we have to get
ride
    of the `where` clause by that logic?
    > >
    > > >The functionality being asked for here is already accepted for
    inclusion to Swift as a method on Sequence named `prefix(while:)`
    (SE-0045):
    > > >
    > > >`for element in array.prefix(while: { someCondition($0) }) {
... }`
    > > >On Mon, Jun 6, 2016 at 14:31 T.J. Usiyan via
    swift-evolution<swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>)>wrote:
    > > >>(As I said, I can live with `while`. I am simply presenting a
    potential point of confusion.)
    > > >>You aren't evaluating the statements in the loop 'while' the
    condition isn't met. The first time that the condition isn't met,
    evaluation of the loop stops. I get that this is technically true
for
    the `while` construct but I suggest that the only reason that it
    works there is that 'stopping the first time that the condition
isn't
    met' *is* the construct. Here, we have a loop that we execute for
    each thing and we're tacking on/intermingling the `while`
construct.
    > > >>
    > > >>
    > > >>
    > > >>On Mon, Jun 6, 2016 at 2:19 PM, Thorsten >>> Seitz<tseitz42@icloud.com >>> <mailto:tseitz42@icloud.com>(mailto:tseitz42@icloud.com >>> <mailto:tseitz42@icloud.com>)(mailto:tseitz42@icloud.com >>> <mailto:tseitz42@icloud.com>)>wrote:
    > > >>>
    > > >>>>Am 06.06.2016 um 19:43 schrieb Tim Vermeulen via >>> swift-evolution<swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>)>:
    > > >>>>
    > > >>>>I also considered `until`, but it would be a bit confusing
    that `where` makes sure a condition is met, while `until` makes
sure
    the condition isn¹t met. I think `while` makes more sense because
it
    corresponds to `break` in the same way that `where` corresponds to
    `continue`.
    > > >>>
    > > >>>That's a good argument! The only drawback is that `while`
and
    `where` look quite similar at a glance.
    > > >>>
    > > >>>-Thorsten
    > > >>>
    > > >>>>
    > > >>>>>`while`, to me, actually reads like it should do what
    `where` does.
    > > >>>>
    > > >>>>To me, `while` reads like it should stop the loop once the
    condition isn¹t met, just like in a while loop.
    > > >>>>
    > > >>>>>I hadn't thought about `while` in this regard but wouldn't
    `until` make more sense? `while`, to me, actually reads like it
    should do what `where` does. In any case, whether it is `while` or
    `where`, this seems like a reasonable feature in my opinion.
    > > >>>>>
    > > >>>>>TJ
    > > >>>>>
    > > >>>>>On Mon, Jun 6, 2016 at 5:15 AM, Tim Vermeulen via
    swift-evolution<swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>)>wrote:
    > > >>>>>>We can already use a where clause in a for loop like
this:
    > > >>>>>>
    > > >>>>>>for element in array where someCondition(element) {
    > > >>>>>>// Š
    > > >>>>>>}
    > > >>>>>>
    > > >>>>>>which basically acts like
    > > >>>>>>
    > > >>>>>>for element in array {
    > > >>>>>>guard someCondition(element) else { continue }
    > > >>>>>>// Š
    > > >>>>>>}
    > > >>>>>>
    > > >>>>>>Sometimes you want to break out of the loop when the
    condition isn¹t met instead. I propose a while clause:
    > > >>>>>>
    > > >>>>>>for element in array while someCondition(element) {
    > > >>>>>>// Š
    > > >>>>>>}
    > > >>>>>>
    > > >>>>>>which would be syntactic sugar for
    > > >>>>>>
    > > >>>>>>for element in array {
    > > >>>>>>guard someCondition(element) else { break }
    > > >>>>>>Š
    > > >>>>>>}
    > > >>>>>>
    > > >>>>>>I can see this particularly being useful if we have a
    sorted array and we already know that once the condition isn¹t met,
    it won¹t be met either for subsequent elements. Another use case
    could be an infinite sequence that we want to cut off somewhere
    (which is simply not possible using a where clause).
    > > >>>>>>_______________________________________________
    > > >>>>>>swift-evolution mailing list
    > > >>>>>>swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto: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>(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto: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>(mailto:swift-evolution@swift.org
    
<mailto:swift-evolution@swift.org>)(mailto: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
    >
    >
    >

_______________________________________________
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

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

The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.

It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.

···

filter() is and prefix(while:) will be available on all sequences. The for...in loop only traverses through sequences.

The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.

On Tue, Jun 7, 2016 at 06:20 Vladimir.S via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> My +1 to the proposal and for Charlie's opinion. I believe `while` in `for`
> loop would be very handy and helpful in some situations, it is a pair for
> existed `where`, its meaning is obvious, and its existence can't depend on
> existence of any method in collections. I'd like to see a formal proposal
> for this feature.
>
> On 07.06.2016 8:18, Charlie Monroe via swift-evolution wrote:
> >I strongly disagree.
> >
> >Exchanging
> >
> >for result in results where result.value != .Warning while result.value !=
> >.Error {
> >/// ...
> >}
> >
> >for either
> >
> >for result in results.filter({ $0.value != .Warning }).prefix(while: {
> >$0.value != .Error })) {
> >/// ...
> >}
> >
> >or
> >
> >for result in results {
> >if result.value == .Warning { continue }
> >if result.value == .Error { break }
> >
> >/// ...
> >}
> >
> >Seems like an absolute step back. Not to mention filter(_:) doesn't return
> >a lazy collection, but will recreate it, while the `where` will do
> >on-the-fly check.
> >
> >>On Jun 7, 2016, at 1:34 AM, Xiaodi Wu via swift-evolution > > >><swift-evolution@swift.org(mailto:swift-evolution@swift.org)<mailto:swift-evolution@swift.org>>wrote:
> >>
> >>Personally, given this discussion and the one about `where` in if and
> >>while statements, I would not be opposed to elimination of `where` in
> >>control statements altogether.
> >>
> >>My reasoning would be that words like filter and prefix unambiguously
> >>indicate what happens to elements of a sequence for which the predicate
> >>returns false, whereas words like where and while are ambiguous.
> >>
> >>On Mon, Jun 6, 2016 at 17:52 Tim Vermeulen<tvermeulen@me.com(mailto:tvermeulen@me.com) > > >><mailto:tvermeulen@me.com>>wrote:
> >>
> >>I didn’t mean we should really get rid of the `where` clause, it’s
> >>great. I guess the point I was trying to make is that we can use a
> >>`where` clause with a `for` loop in Swift, despite the existence of
> >>the `filter` method. So despite `prefix(while:)` in Swift 3, there
> >>might be room for a `while` clause. I think it makes the code a lot
> >>more readable, much like how `where` can make a `for` loop a lot more
> >>readable than using `filter`.
> >>
> >>>The burden of proof for adding new features is different from that
> >>for taking away existing features.
> >>>
> >>>If a feature doesn't yet exist, a successful proposal will show how
> >>it provides additional and non-trivial utility. If a feature already
> >>exists, a successful proposal to remove it will show how it is
> >>harmful to the language or contrary to the direction in which it is
> >>evolving.
> >>>
> >>>On Mon, Jun 6, 2016 at 15:38 Tim Vermeulen<tvermeulen@me.com(mailto:tvermeulen@me.com) > > >><mailto:tvermeulen@me.com>(mailto:tvermeulen@me.com > > >><mailto:tvermeulen@me.com>)>wrote:
> >>>>The functionality of the `where` clause in `for` loops also
> >>already can be mimicked using `filter`. Wouldn’t we have to get ride
> >>of the `where` clause by that logic?
> >>>>
> >>>>>The functionality being asked for here is already accepted for
> >>inclusion to Swift as a method on Sequence named `prefix(while:)`
> >>(SE-0045):
> >>>>>
> >>>>>`for element in array.prefix(while: { someCondition($0) }) { ... }`
> >>>>>On Mon, Jun 6, 2016 at 14:31 T.J. Usiyan via > > >>swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org) > > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org > > >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org > > >><mailto:swift-evolution@swift.org>)>wrote:
> >>>>>>(As I said, I can live with `while`. I am simply presenting a
> >>potential point of confusion.)
> >>>>>>You aren't evaluating the statements in the loop 'while' the
> >>condition isn't met. The first time that the condition isn't met,
> >>evaluation of the loop stops. I get that this is technically true for
> >>the `while` construct but I suggest that the only reason that it
> >>works there is that 'stopping the first time that the condition isn't
> >>met' *is* the construct. Here, we have a loop that we execute for
> >>each thing and we're tacking on/intermingling the `while` construct.
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>On Mon, Jun 6, 2016 at 2:19 PM, Thorsten > > >>Seitz<tseitz42@icloud.com(mailto:tseitz42@icloud.com) > > >><mailto:tseitz42@icloud.com>(mailto:tseitz42@icloud.com > > >><mailto:tseitz42@icloud.com>)(mailto:tseitz42@icloud.com > > >><mailto:tseitz42@icloud.com>)>wrote:
> >>>>>>>
> >>>>>>>>Am 06.06.2016 um 19:43 schrieb Tim Vermeulen via
> >>swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)>:
> >>>>>>>>
> >>>>>>>>I also considered `until`, but it would be a bit confusing
> >>that `where` makes sure a condition is met, while `until` makes sure
> >>the condition isn’t met. I think `while` makes more sense because it
> >>corresponds to `break` in the same way that `where` corresponds to
> >>`continue`.
> >>>>>>>
> >>>>>>>That's a good argument! The only drawback is that `while` and
> >>`where` look quite similar at a glance.
> >>>>>>>
> >>>>>>>-Thorsten
> >>>>>>>
> >>>>>>>>
> >>>>>>>>>`while`, to me, actually reads like it should do what
> >>`where` does.
> >>>>>>>>
> >>>>>>>>To me, `while` reads like it should stop the loop once the
> >>condition isn’t met, just like in a while loop.
> >>>>>>>>
> >>>>>>>>>I hadn't thought about `while` in this regard but wouldn't
> >>`until` make more sense? `while`, to me, actually reads like it
> >>should do what `where` does. In any case, whether it is `while` or
> >>`where`, this seems like a reasonable feature in my opinion.
> >>>>>>>>>
> >>>>>>>>>TJ
> >>>>>>>>>
> >>>>>>>>>On Mon, Jun 6, 2016 at 5:15 AM, Tim Vermeulen via
> >>swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)>wrote:
> >>>>>>>>>>We can already use a where clause in a for loop like this:
> >>>>>>>>>>
> >>>>>>>>>>for element in array where someCondition(element) {
> >>>>>>>>>>// …
> >>>>>>>>>>}
> >>>>>>>>>>
> >>>>>>>>>>which basically acts like
> >>>>>>>>>>
> >>>>>>>>>>for element in array {
> >>>>>>>>>>guard someCondition(element) else { continue }
> >>>>>>>>>>// …
> >>>>>>>>>>}
> >>>>>>>>>>
> >>>>>>>>>>Sometimes you want to break out of the loop when the
> >>condition isn’t met instead. I propose a while clause:
> >>>>>>>>>>
> >>>>>>>>>>for element in array while someCondition(element) {
> >>>>>>>>>>// …
> >>>>>>>>>>}
> >>>>>>>>>>
> >>>>>>>>>>which would be syntactic sugar for
> >>>>>>>>>>
> >>>>>>>>>>for element in array {
> >>>>>>>>>>guard someCondition(element) else { break }
> >>>>>>>>>>…
> >>>>>>>>>>}
> >>>>>>>>>>
> >>>>>>>>>>I can see this particularly being useful if we have a
> >>sorted array and we already know that once the condition isn’t met,
> >>it won’t be met either for subsequent elements. Another use case
> >>could be an infinite sequence that we want to cut off somewhere
> >>(which is simply not possible using a where clause).
> >>>>>>>>>>_______________________________________________
> >>>>>>>>>>swift-evolution mailing list
> >>>>>>>>>>swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto: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)
> >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto: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)
> >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> >><mailto:swift-evolution@swift.org>)(mailto: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)<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)<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
> >
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> https://lists.swift.org/mailman/listinfo/swift-evolution

The where_clause appears in the for in statement

for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block

It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):

for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
when_clause : 'when' expression

and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.

I'd say that in both cases, combining chaining and statements is marginally less good than either using standalone chaining or statements without chaining. But as I say this, I know as a fact, I fully intend to use `sequence(_:, next:).take(while:)` with for0in statements, so I'm starting from a hypocritical vantage point.

To summarize, I'm more +0.01 than I am -0.01 on this.

-- E
p.s. Sorry, wux

···

On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution <swift-evolution@swift.org> wrote:

The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.

It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.

> The meaning of the proposed while is not at all a pair for where, since
where clauses in while loops would do the same thing as while clauses in
for loops. That's crazy.

It sounds crazy, but it’s the nature of the while loop. A where clause in
a while loop also has a different result than a where clause in a for loop.

I know. And SE-0099 proposed to eliminate it, and I am very supportive of
that. For all of the reasons outlined in that conversation (including the
different behaviors in while and for loops), I arrive at the conclusion
that `where` is unsuitable for use in all condition statements and would
support its complete elimination from the language.

···

On Tue, Jun 7, 2016 at 2:16 PM, Tim Vermeulen <tvermeulen@me.com> wrote:

> filter() is and prefix(while:) will be available on all sequences. The
for...in loop only traverses through sequences.
>
> The meaning of the proposed while is not at all a pair for where, since
where clauses in while loops would do the same thing as while clauses in
for loops. That's crazy.
>
> On Tue, Jun 7, 2016 at 06:20 Vladimir.S via swift-evolution< > swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> > My +1 to the proposal and for Charlie's opinion. I believe `while` in
`for`
> > loop would be very handy and helpful in some situations, it is a pair
for
> > existed `where`, its meaning is obvious, and its existence can't
depend on
> > existence of any method in collections. I'd like to see a formal
proposal
> > for this feature.
> >
> > On 07.06.2016 8:18, Charlie Monroe via swift-evolution wrote:
> > >I strongly disagree.
> > >
> > >Exchanging
> > >
> > >for result in results where result.value != .Warning while
result.value !=
> > >.Error {
> > >/// ...
> > >}
> > >
> > >for either
> > >
> > >for result in results.filter({ $0.value != .Warning }).prefix(while: {
> > >$0.value != .Error })) {
> > >/// ...
> > >}
> > >
> > >or
> > >
> > >for result in results {
> > >if result.value == .Warning { continue }
> > >if result.value == .Error { break }
> > >
> > >/// ...
> > >}
> > >
> > >Seems like an absolute step back. Not to mention filter(_:) doesn't
return
> > >a lazy collection, but will recreate it, while the `where` will do
> > >on-the-fly check.
> > >
> > >>On Jun 7, 2016, at 1:34 AM, Xiaodi Wu via swift-evolution > > > >><swift-evolution@swift.org(mailto:swift-evolution@swift.org)<mailto: > swift-evolution@swift.org>>wrote:
> > >>
> > >>Personally, given this discussion and the one about `where` in if and
> > >>while statements, I would not be opposed to elimination of `where` in
> > >>control statements altogether.
> > >>
> > >>My reasoning would be that words like filter and prefix unambiguously
> > >>indicate what happens to elements of a sequence for which the
predicate
> > >>returns false, whereas words like where and while are ambiguous.
> > >>
> > >>On Mon, Jun 6, 2016 at 17:52 Tim Vermeulen<tvermeulen@me.com(mailto: > tvermeulen@me.com) > > > >><mailto:tvermeulen@me.com>>wrote:
> > >>
> > >>I didn’t mean we should really get rid of the `where` clause, it’s
> > >>great. I guess the point I was trying to make is that we can use a
> > >>`where` clause with a `for` loop in Swift, despite the existence of
> > >>the `filter` method. So despite `prefix(while:)` in Swift 3, there
> > >>might be room for a `while` clause. I think it makes the code a lot
> > >>more readable, much like how `where` can make a `for` loop a lot more
> > >>readable than using `filter`.
> > >>
> > >>>The burden of proof for adding new features is different from that
> > >>for taking away existing features.
> > >>>
> > >>>If a feature doesn't yet exist, a successful proposal will show how
> > >>it provides additional and non-trivial utility. If a feature already
> > >>exists, a successful proposal to remove it will show how it is
> > >>harmful to the language or contrary to the direction in which it is
> > >>evolving.
> > >>>
> > >>>On Mon, Jun 6, 2016 at 15:38 Tim Vermeulen<tvermeulen@me.com > (mailto:tvermeulen@me.com) > > > >><mailto:tvermeulen@me.com>(mailto:tvermeulen@me.com > > > >><mailto:tvermeulen@me.com>)>wrote:
> > >>>>The functionality of the `where` clause in `for` loops also
> > >>already can be mimicked using `filter`. Wouldn’t we have to get ride
> > >>of the `where` clause by that logic?
> > >>>>
> > >>>>>The functionality being asked for here is already accepted for
> > >>inclusion to Swift as a method on Sequence named `prefix(while:)`
> > >>(SE-0045):
> > >>>>>
> > >>>>>`for element in array.prefix(while: { someCondition($0) }) { ...
}`
> > >>>>>On Mon, Jun 6, 2016 at 14:31 T.J. Usiyan via
> > >>swift-evolution<swift-evolution@swift.org(mailto:
swift-evolution@swift.org)
> > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)>wrote:
> > >>>>>>(As I said, I can live with `while`. I am simply presenting a
> > >>potential point of confusion.)
> > >>>>>>You aren't evaluating the statements in the loop 'while' the
> > >>condition isn't met. The first time that the condition isn't met,
> > >>evaluation of the loop stops. I get that this is technically true for
> > >>the `while` construct but I suggest that the only reason that it
> > >>works there is that 'stopping the first time that the condition isn't
> > >>met' *is* the construct. Here, we have a loop that we execute for
> > >>each thing and we're tacking on/intermingling the `while` construct.
> > >>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>>On Mon, Jun 6, 2016 at 2:19 PM, Thorsten > > > >>Seitz<tseitz42@icloud.com(mailto:tseitz42@icloud.com) > > > >><mailto:tseitz42@icloud.com>(mailto:tseitz42@icloud.com > > > >><mailto:tseitz42@icloud.com>)(mailto:tseitz42@icloud.com > > > >><mailto:tseitz42@icloud.com>)>wrote:
> > >>>>>>>
> > >>>>>>>>Am 06.06.2016 um 19:43 schrieb Tim Vermeulen via > > > >>swift-evolution<swift-evolution@swift.org(mailto:
swift-evolution@swift.org)
> > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)>:
> > >>>>>>>>
> > >>>>>>>>I also considered `until`, but it would be a bit confusing
> > >>that `where` makes sure a condition is met, while `until` makes sure
> > >>the condition isn’t met. I think `while` makes more sense because it
> > >>corresponds to `break` in the same way that `where` corresponds to
> > >>`continue`.
> > >>>>>>>
> > >>>>>>>That's a good argument! The only drawback is that `while` and
> > >>`where` look quite similar at a glance.
> > >>>>>>>
> > >>>>>>>-Thorsten
> > >>>>>>>
> > >>>>>>>>
> > >>>>>>>>>`while`, to me, actually reads like it should do what
> > >>`where` does.
> > >>>>>>>>
> > >>>>>>>>To me, `while` reads like it should stop the loop once the
> > >>condition isn’t met, just like in a while loop.
> > >>>>>>>>
> > >>>>>>>>>I hadn't thought about `while` in this regard but wouldn't
> > >>`until` make more sense? `while`, to me, actually reads like it
> > >>should do what `where` does. In any case, whether it is `while` or
> > >>`where`, this seems like a reasonable feature in my opinion.
> > >>>>>>>>>
> > >>>>>>>>>TJ
> > >>>>>>>>>
> > >>>>>>>>>On Mon, Jun 6, 2016 at 5:15 AM, Tim Vermeulen via
> > >>swift-evolution<swift-evolution@swift.org(mailto:
swift-evolution@swift.org)
> > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)>wrote:
> > >>>>>>>>>>We can already use a where clause in a for loop like this:
> > >>>>>>>>>>
> > >>>>>>>>>>for element in array where someCondition(element) {
> > >>>>>>>>>>// …
> > >>>>>>>>>>}
> > >>>>>>>>>>
> > >>>>>>>>>>which basically acts like
> > >>>>>>>>>>
> > >>>>>>>>>>for element in array {
> > >>>>>>>>>>guard someCondition(element) else { continue }
> > >>>>>>>>>>// …
> > >>>>>>>>>>}
> > >>>>>>>>>>
> > >>>>>>>>>>Sometimes you want to break out of the loop when the
> > >>condition isn’t met instead. I propose a while clause:
> > >>>>>>>>>>
> > >>>>>>>>>>for element in array while someCondition(element) {
> > >>>>>>>>>>// …
> > >>>>>>>>>>}
> > >>>>>>>>>>
> > >>>>>>>>>>which would be syntactic sugar for
> > >>>>>>>>>>
> > >>>>>>>>>>for element in array {
> > >>>>>>>>>>guard someCondition(element) else { break }
> > >>>>>>>>>>…
> > >>>>>>>>>>}
> > >>>>>>>>>>
> > >>>>>>>>>>I can see this particularly being useful if we have a
> > >>sorted array and we already know that once the condition isn’t met,
> > >>it won’t be met either for subsequent elements. Another use case
> > >>could be an infinite sequence that we want to cut off somewhere
> > >>(which is simply not possible using a where clause).
> > >>>>>>>>>>_______________________________________________
> > >>>>>>>>>>swift-evolution mailing list
> > >>>>>>>>>>swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto: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)
> > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto: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)
> > >><mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org
> > >><mailto:swift-evolution@swift.org>)(mailto: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)<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)<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
> > >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>

It may be workable if you can have only one or the other, but mixing and
matching them as proposed above would be a world of hurt:

for foo in bar where condition1 while condition2 { ... }

If condition1 and condition2 both evaluate to true, then whether you
continue or break would depend on the relative order of where and while;
for generality, you would want to allow both `for...in...where...while` and
`for...in...while...where`, and likely `for...in...while...where...while`,
etc. There is nothing in the meaning of those words that would suggest that
`while...where` behaves differently from `where...while`, etc. This is why
words like "break" and "continue" are IMO far superior.

···

On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution < > swift-evolution@swift.org> wrote:

The meaning of the proposed while is not at all a pair for where, since
where clauses in while loops would do the same thing as while clauses in
for loops. That's crazy.

It sounds crazy, but it’s the nature of the while loop. A where clause in
a while loop also has a different result than a where clause in a for loop.

The where_clause appears in the for in statement

for_in_statement : 'for' 'case'? pattern 'in' expression where_clause?
code_block

It's syntactic sugar because the expression can be already be limited
through functional chaining of some sort or another. At the same time, it's
nice and pleasant to have `where` and I'm not itching to throw it out. The
same courtesy could be easily extend to `when` (because I don't really want
to use the `while` keyword here, but I could easily be convinced otherwise
because I don't have a strong stance either way):

for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause |
when_clause)? code_block
when_clause : 'when' expression

and again it could be nice and pleasant to have, although not necessary.
The question comes down to how much does the language benefit by this sugar.

I'd say that in both cases, combining chaining and statements is
marginally *less good* than either using standalone chaining or
statements without chaining. But as I say this, I know as a fact, I fully
intend to use `sequence(_:, next:).take(while:)` with for0in statements, so
I'm starting from a hypocritical vantage point.

To summarize, I'm more +0.01 than I am -0.01 on this.

-- E
p.s. Sorry, wux

It may be workable if you can have only one or the other, but mixing and
matching them as proposed above would be a world of hurt:

for foo in bar where condition1 while condition2 { ... }

If condition1 and condition2 both evaluate to true,

s/true/false/

···

On Tue, Jun 7, 2016 at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

then whether you continue or break would depend on the relative order of
where and while; for generality, you would want to allow both
`for...in...where...while` and `for...in...while...where`, and likely
`for...in...while...where...while`, etc. There is nothing in the meaning of
those words that would suggest that `while...where` behaves differently
from `where...while`, etc. This is why words like "break" and "continue"
are IMO far superior.

On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution < >> swift-evolution@swift.org> wrote:

The meaning of the proposed while is not at all a pair for where, since
where clauses in while loops would do the same thing as while clauses in
for loops. That's crazy.

It sounds crazy, but it’s the nature of the while loop. A where clause in
a while loop also has a different result than a where clause in a for loop.

The where_clause appears in the for in statement

for_in_statement : 'for' 'case'? pattern 'in' expression where_clause?
code_block

It's syntactic sugar because the expression can be already be limited
through functional chaining of some sort or another. At the same time, it's
nice and pleasant to have `where` and I'm not itching to throw it out. The
same courtesy could be easily extend to `when` (because I don't really want
to use the `while` keyword here, but I could easily be convinced otherwise
because I don't have a strong stance either way):

for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause |
when_clause)? code_block
when_clause : 'when' expression

and again it could be nice and pleasant to have, although not necessary.
The question comes down to how much does the language benefit by this sugar.

I'd say that in both cases, combining chaining and statements is
marginally *less good* than either using standalone chaining or
statements without chaining. But as I say this, I know as a fact, I fully
intend to use `sequence(_:, next:).take(while:)` with for0in statements, so
I'm starting from a hypocritical vantage point.

To summarize, I'm more +0.01 than I am -0.01 on this.

-- E
p.s. Sorry, wux

I’ve been thinking about this for a bit now, and I think it would make most sense to evaluate these clauses from left to right. However, cases where the order matters are very uncommon, and I would rather have the power to choose which clause is evaluated first than to have a forced default order. Either way I don’t see this as a reason not to allow combining the two clauses because IMO it can lead to some very clean code. For instance, say we want to loop through all even fibonacci numbers below 4 million (see problem #2 from project euler), we could do this:

`for number in fibonacci where number % 2 == 0 while number < 4_000_000 { }`

I could have ordered the two clauses in any way I want. If combining the clauses weren’t allowed, I’d have to put (at least) one of them inside the block, which would be a (minor) pain.

I don’t currently have a very strong opinion about the order of evaluation, so I might be convinced otherwise. But combining the two clauses is so powerful that I don’t think it’s worth to get rid of just because of an edge case.

···

It may be workable if you can have only one or the other, but mixing and matching them as proposed above would be a world of hurt:

for foo in bar where condition1 while condition2 { ... }

If condition1 and condition2 both evaluate to true, then whether you continue or break would depend on the relative order of where and while; for generality, you would want to allow both `for...in...where...while` and `for...in...while...where`, and likely `for...in...while...where...while`, etc. There is nothing in the meaning of those words that would suggest that `while...where` behaves differently from `where...while`, etc. This is why words like "break" and "continue" are IMO far superior.

On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com(mailto:erica@ericasadun.com)>wrote:
>
> > On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> > > The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.
> >
> > It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.
>
> The where_clause appears in the for in statement
>
> for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block
>
> It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):
>
> for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
> when_clause : 'when' expression
>
> and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.
>
> I'd say that in both cases, combining chaining and statements is marginallyless goodthan either using standalone chaining or statements without chaining. But as I say this, I know as a fact, I fully intend to use `sequence(_:, next:).take(while:)` with for0in statements, so I'm starting from a hypocritical vantage point.
>
> To summarize, I'm more +0.01 than I am -0.01 on this.
>
> -- E
> p.s. Sorry, wux
>
>

I think `when` would be pretty confusing. If I didn’t know what it meant and I had to guess, I’d probably think that it means what `where` currently means.

Calling it `while` could perhaps cause confusing with the while loop, but it means the same thing in both contexts so people might already feel familiar with it.

···

> On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> > The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.
>
> It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.
The where_clause appears in the for in statement

for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block

It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):

for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
when_clause : 'when' expression

and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.

I'd say that in both cases, combining chaining and statements is marginallyless goodthan either using standalone chaining or statements without chaining. But as I say this, I know as a fact, I fully intend to use `sequence(_:, next:).take(while:)` with for0in statements, so I'm starting from a hypocritical vantage point.

To summarize, I'm more +0.01 than I am -0.01 on this.

-- E
p.s. Sorry, wux

I’ve been thinking about this for a bit now, and I think it would make
most sense to evaluate these clauses from left to right. However, cases
where the order matters are very uncommon, and I would rather have the
power to choose which clause is evaluated first than to have a forced
default order. Either way I don’t see this as a reason not to allow
combining the two clauses because IMO it can lead to some very clean code.
For instance, say we want to loop through all even fibonacci numbers below
4 million (see problem #2 from project euler), we could do this:

`for number in fibonacci where number % 2 == 0 while number < 4_000_000 {
}`

This statement looks like spaghetti to me. I would not at all support
extending the language to permit it. Do you really think it's more readable
than going step-by-step?

let numbers = fibonacci.prefix { $0 < 4_000_000 }
for number in numbers where number % 2 == 0 {
  // ...
}

or just:

let numbers = fibonacci.prefix { $0 < 4_000_000 }
let evens = numbers.filter { $0 % 2 == 0 }
for number in evens {
  // ...
}
···

On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen <tvermeulen@me.com> wrote:

I could have ordered the two clauses in any way I want. If combining the
clauses weren’t allowed, I’d have to put (at least) one of them inside the
block, which would be a (minor) pain.

I don’t currently have a very strong opinion about the order of
evaluation, so I might be convinced otherwise. But combining the two
clauses is so powerful that I don’t think it’s worth to get rid of just
because of an edge case.

> It may be workable if you can have only one or the other, but mixing and
matching them as proposed above would be a world of hurt:
>
> ```
> for foo in bar where condition1 while condition2 { ... }
> ```
>
> If condition1 and condition2 both evaluate to true, then whether you
continue or break would depend on the relative order of where and while;
for generality, you would want to allow both `for...in...where...while` and
`for...in...while...where`, and likely `for...in...while...where...while`,
etc. There is nothing in the meaning of those words that would suggest that
`while...where` behaves differently from `where...while`, etc. This is why
words like "break" and "continue" are IMO far superior.
>
>
> On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com(mailto: > erica@ericasadun.com)>wrote:
> >
> > > On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution< > swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> > > > The meaning of the proposed while is not at all a pair for where,
since where clauses in while loops would do the same thing as while clauses
in for loops. That's crazy.
> > >
> > > It sounds crazy, but it’s the nature of the while loop. A where
clause in a while loop also has a different result than a where clause in a
for loop.
> >
> > The where_clause appears in the for in statement
> >
> > for_in_statement : 'for' 'case'? pattern 'in' expression where_clause?
code_block
> >
> > It's syntactic sugar because the expression can be already be limited
through functional chaining of some sort or another. At the same time, it's
nice and pleasant to have `where` and I'm not itching to throw it out. The
same courtesy could be easily extend to `when` (because I don't really want
to use the `while` keyword here, but I could easily be convinced otherwise
because I don't have a strong stance either way):
> >
> > for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause
> when_clause)? code_block
> > when_clause : 'when' expression
> >
> > and again it could be nice and pleasant to have, although not
necessary. The question comes down to how much does the language benefit by
this sugar.
> >
> > I'd say that in both cases, combining chaining and statements is
marginallyless goodthan either using standalone chaining or statements
without chaining. But as I say this, I know as a fact, I fully intend to
use `sequence(_:, next:).take(while:)` with for0in statements, so I'm
starting from a hypocritical vantage point.
> >
> > To summarize, I'm more +0.01 than I am -0.01 on this.
> >
> > -- E
> > p.s. Sorry, wux
> >
> >
>
>
>

IMO `.prefix` is just not the equal alternative for as proposed `while` : in case of 'while' expression `number < 4_000_000` will be calculated *only* for those who `number % 2 == 0`. In case of `prefix` - the expression will be processed for each `number` and only after this filtered by `number % 2`. Let's assume we need to check for some veryExpensiveTest(number):

for number in fibonacci where number % 2 == 0 while veryExpensiveTest(number) {}

let numbers = fibonacci.prefix { veryExpensiveTest($0) }
for number in numbers where number % 2 == 0 {}

So, `while` for `for` loops just can't be always replaced with `prefix`

···

On 08.06.2016 2:02, Xiaodi Wu via swift-evolution wrote:

On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen <tvermeulen@me.com > <mailto:tvermeulen@me.com>> wrote:

    I’ve been thinking about this for a bit now, and I think it would make
    most sense to evaluate these clauses from left to right. However, cases
    where the order matters are very uncommon, and I would rather have the
    power to choose which clause is evaluated first than to have a forced
    default order. Either way I don’t see this as a reason not to allow
    combining the two clauses because IMO it can lead to some very clean
    code. For instance, say we want to loop through all even fibonacci
    numbers below 4 million (see problem #2 from project euler), we could
    do this:

    `for number in fibonacci where number % 2 == 0 while number < 4_000_000
    { }`

This statement looks like spaghetti to me. I would not at all support
extending the language to permit it. Do you really think it's more readable
than going step-by-step?

let numbers = fibonacci.prefix { $0 < 4_000_000 }
for number in numbers where number % 2 == 0 {
  // ...
}

or just:

let numbers = fibonacci.prefix { $0 < 4_000_000 }
let evens = numbers.filter { $0 % 2 == 0 }
for number in evens {
  // ...
}

    I could have ordered the two clauses in any way I want. If combining
    the clauses weren’t allowed, I’d have to put (at least) one of them
    inside the block, which would be a (minor) pain.

    I don’t currently have a very strong opinion about the order of
    evaluation, so I might be convinced otherwise. But combining the two
    clauses is so powerful that I don’t think it’s worth to get rid of just
    because of an edge case.

    > It may be workable if you can have only one or the other, but mixing and matching them as proposed above would be a world of hurt:
    >
    > ```
    > for foo in bar where condition1 while condition2 { ... }
    > ```
    >
    > If condition1 and condition2 both evaluate to true, then whether you continue or break would depend on the relative order of where and while; for generality, you would want to allow both `for...in...where...while` and `for...in...while...where`, and likely `for...in...while...where...while`, etc. There is nothing in the meaning of those words that would suggest that `while...where` behaves differently from `where...while`, etc. This is why words like "break" and "continue" are IMO far superior.
    >
    > On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com > <mailto:erica@ericasadun.com>(mailto:erica@ericasadun.com > <mailto:erica@ericasadun.com>)>wrote:
    > >
    > > > On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution<swift-evolution@swift.org > <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org > <mailto:swift-evolution@swift.org>)>wrote:
    > > > > The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.
    > > >
    > > > It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.
    > >
    > > The where_clause appears in the for in statement
    > >
    > > for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block
    > >
    > > It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):
    > >
    > > for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
    > > when_clause : 'when' expression
    > >
    > > and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.
    > >
    > > I'd say that in both cases, combining chaining and statements is
    marginallyless goodthan either using standalone chaining or statements
    without chaining. But as I say this, I know as a fact, I fully intend
    to use `sequence(_:, next:).take(while:)` with for0in statements, so
    I'm starting from a hypocritical vantage point.
    > >
    > > To summarize, I'm more +0.01 than I am -0.01 on this.
    > >
    > > -- E
    > > p.s. Sorry, wux
    > >
    >

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

Interesting. What if you put newlines before `where` and `while`? It’s hard to get the spacing right in a mailing list, but I tried it in Xcode and it looks really good to me (except for the compiler error it currently produces). Way better than the way I wrote it initially and the alternatives you mentioned.

for number in fibonacci
    where number % 2 == 0
    while number < 4_000_000 { }

···

On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen<tvermeulen@me.com(mailto:tvermeulen@me.com)>wrote:
> I’ve been thinking about this for a bit now, and I think it would make most sense to evaluate these clauses from left to right. However, cases where the order matters are very uncommon, and I would rather have the power to choose which clause is evaluated first than to have a forced default order. Either way I don’t see this as a reason not to allow combining the two clauses because IMO it can lead to some very clean code. For instance, say we want to loop through all even fibonacci numbers below 4 million(see problem #2 from project euler), we could do this:
>
> `for number in fibonacci where number % 2 == 0 while number<4_000_000 { }`
This statement looks like spaghetti to me. I would not at all support extending the language to permit it. Do you really think it's more readable than going step-by-step?

let numbers = fibonacci.prefix { $0<4_000_000 }
for number in numbers where number % 2 == 0 {
// ...
}

or just:

let numbers = fibonacci.prefix { $0<4_000_000 }
let evens = numbers.filter { $0 % 2 == 0 }
for number in evens {
// ...
}

>
> I could have ordered the two clauses in any way I want. If combining the clauses weren’t allowed, I’d have to put (at least) one of them inside the block, which would be a (minor) pain.
>
> I don’t currently have a very strong opinion about the order of evaluation, so I might be convinced otherwise. But combining the two clauses is so powerful that I don’t think it’s worth to get rid of just because of an edge case.
>
> >It may be workable if you can have only one or the other, but mixing and matching them as proposed above would be a world of hurt:
> >
> >```
> >for foo in bar where condition1 while condition2 { ... }
> >```
> >
> >If condition1 and condition2 both evaluate to true, then whether you continue or break would depend on the relative order of where and while; for generality, you would want to allow both `for...in...where...while` and `for...in...while...where`, and likely `for...in...while...where...while`, etc. There is nothing in the meaning of those words that would suggest that `while...where` behaves differently from `where...while`, etc. This is why words like "break" and "continue" are IMO far superior.
> >
> >
> >On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com(mailto:erica@ericasadun.com)(mailto:erica@ericasadun.com)>wrote:
> >>
> >>>On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)(mailto:swift-evolution@swift.org)>wrote:
> >>>>The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.
> >>>
> >>>It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.
> >>
> >>The where_clause appears in the for in statement
> >>
> >>for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block
> >>
> >>It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):
> >>
> >>for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
> >>when_clause : 'when' expression
> >>
> >>and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.
> >>
> >>I'd say that in both cases, combining chaining and statements is marginallyless goodthan either using standalone chaining or statements without chaining. But as I say this, I know as a fact, I fully intend to use `sequence(_:, next:).take(while:)` with for0in statements, so I'm starting from a hypocritical vantage point.
> >>
> >>To summarize, I'm more +0.01 than I am -0.01 on this.
> >>
> >>-- E
> >>p.s. Sorry, wux
> >>
> >>
> >
> >
> >

Clearly, if the predicate for prefix is very expensive, it can be evaluated
after filtering for evens, or it can be evaluated inside the loop. And that
goes to my point: writing things out explicitly will cause you to think
about these issues, whereas a `while` clause tends to obscure them.

···

On Wed, Jun 8, 2016 at 10:40 Vladimir.S <svabox@gmail.com> wrote:

IMO `.prefix` is just not the equal alternative for as proposed `while` :
in case of 'while' expression `number < 4_000_000` will be calculated
*only* for those who `number % 2 == 0`. In case of `prefix` - the
expression will be processed for each `number` and only after this filtered
by `number % 2`. Let's assume we need to check for some
veryExpensiveTest(number):

for number in fibonacci where number % 2 == 0 while
veryExpensiveTest(number) {}

let numbers = fibonacci.prefix { veryExpensiveTest($0) }
for number in numbers where number % 2 == 0 {}

So, `while` for `for` loops just can't be always replaced with `prefix`

On 08.06.2016 2:02, Xiaodi Wu via swift-evolution wrote:
> On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen <tvermeulen@me.com > > <mailto:tvermeulen@me.com>> wrote:
>
> I’ve been thinking about this for a bit now, and I think it would
make
> most sense to evaluate these clauses from left to right. However,
cases
> where the order matters are very uncommon, and I would rather have
the
> power to choose which clause is evaluated first than to have a forced
> default order. Either way I don’t see this as a reason not to allow
> combining the two clauses because IMO it can lead to some very clean
> code. For instance, say we want to loop through all even fibonacci
> numbers below 4 million (see problem #2 from project euler), we
could
> do this:
>
> `for number in fibonacci where number % 2 == 0 while number <
4_000_000
> { }`
>
>
> This statement looks like spaghetti to me. I would not at all support
> extending the language to permit it. Do you really think it's more
readable
> than going step-by-step?
>
> ```
> let numbers = fibonacci.prefix { $0 < 4_000_000 }
> for number in numbers where number % 2 == 0 {
> // ...
> }
> ```
>
> or just:
>
> ```
> let numbers = fibonacci.prefix { $0 < 4_000_000 }
> let evens = numbers.filter { $0 % 2 == 0 }
> for number in evens {
> // ...
> }
> ```
>
>
> I could have ordered the two clauses in any way I want. If combining
> the clauses weren’t allowed, I’d have to put (at least) one of them
> inside the block, which would be a (minor) pain.
>
> I don’t currently have a very strong opinion about the order of
> evaluation, so I might be convinced otherwise. But combining the two
> clauses is so powerful that I don’t think it’s worth to get rid of
just
> because of an edge case.
>
> > It may be workable if you can have only one or the other, but
mixing and matching them as proposed above would be a world of hurt:
> >
> > ```
> > for foo in bar where condition1 while condition2 { ... }
> > ```
> >
> > If condition1 and condition2 both evaluate to true, then whether
you continue or break would depend on the relative order of where and
while; for generality, you would want to allow both
`for...in...where...while` and `for...in...while...where`, and likely
`for...in...while...where...while`, etc. There is nothing in the meaning of
those words that would suggest that `while...where` behaves differently
from `where...while`, etc. This is why words like "break" and "continue"
are IMO far superior.
> >
> >
> > On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com > > <mailto:erica@ericasadun.com>(mailto:erica@ericasadun.com > > <mailto:erica@ericasadun.com>)>wrote:
> > >
> > > > On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution< > swift-evolution@swift.org > > <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org > > <mailto:swift-evolution@swift.org>)>wrote:
> > > > > The meaning of the proposed while is not at all a pair for
where, since where clauses in while loops would do the same thing as while
clauses in for loops. That's crazy.
> > > >
> > > > It sounds crazy, but it’s the nature of the while loop. A
where clause in a while loop also has a different result than a where
clause in a for loop.
> > >
> > > The where_clause appears in the for in statement
> > >
> > > for_in_statement : 'for' 'case'? pattern 'in' expression
where_clause? code_block
> > >
> > > It's syntactic sugar because the expression can be already be
limited through functional chaining of some sort or another. At the same
time, it's nice and pleasant to have `where` and I'm not itching to throw
it out. The same courtesy could be easily extend to `when` (because I don't
really want to use the `while` keyword here, but I could easily be
convinced otherwise because I don't have a strong stance either way):
> > >
> > > for_in_statement : 'for' 'case'? pattern 'in' expression
(where_clause | when_clause)? code_block
> > > when_clause : 'when' expression
> > >
> > > and again it could be nice and pleasant to have, although not
necessary. The question comes down to how much does the language benefit by
this sugar.
> > >
> > > I'd say that in both cases, combining chaining and statements is
> marginallyless goodthan either using standalone chaining or
statements
> without chaining. But as I say this, I know as a fact, I fully intend
> to use `sequence(_:, next:).take(while:)` with for0in statements, so
> I'm starting from a hypocritical vantage point.
> > >
> > > To summarize, I'm more +0.01 than I am -0.01 on this.
> > >
> > > -- E
> > > p.s. Sorry, wux
> > >
> > >
> >
> >
> >
>
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

This is a really strong argument in my opinion. If we don’t add a `while` to for loops, then in some situations we will have to rewrite a `where` clause to something potentially less elegant, given that we don’t want to give up performance.

···

IMO `.prefix` is just not the equal alternative for as proposed `while` :
in case of 'while' expression `number<4_000_000` will be calculated
*only* for those who `number % 2 == 0`. In case of `prefix` - the
expression will be processed for each `number` and only after this filtered
by `number % 2`. Let's assume we need to check for some
veryExpensiveTest(number):

for number in fibonacci where number % 2 == 0 while
veryExpensiveTest(number) {}

let numbers = fibonacci.prefix { veryExpensiveTest($0) }
for number in numbers where number % 2 == 0 {}

So, `while` for `for` loops just can't be always replaced with `prefix`

On 08.06.2016 2:02, Xiaodi Wu via swift-evolution wrote:
> On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen<tvermeulen@me.com > > <mailto:tvermeulen@me.com>>wrote:
>
> I’ve been thinking about this for a bit now, and I think it would make
> most sense to evaluate these clauses from left to right. However, cases
> where the order matters are very uncommon, and I would rather have the
> power to choose which clause is evaluated first than to have a forced
> default order. Either way I don’t see this as a reason not to allow
> combining the two clauses because IMO it can lead to some very clean
> code. For instance, say we want to loop through all even fibonacci
> numbers below 4 million (see problem #2 from project euler), we could
> do this:
>
> `for number in fibonacci where number % 2 == 0 while number<4_000_000
> { }`
>
>
> This statement looks like spaghetti to me. I would not at all support
> extending the language to permit it. Do you really think it's more readable
> than going step-by-step?
>
> ```
> let numbers = fibonacci.prefix { $0<4_000_000 }
> for number in numbers where number % 2 == 0 {
> // ...
> }
> ```
>
> or just:
>
> ```
> let numbers = fibonacci.prefix { $0<4_000_000 }
> let evens = numbers.filter { $0 % 2 == 0 }
> for number in evens {
> // ...
> }
> ```
>
>
> I could have ordered the two clauses in any way I want. If combining
> the clauses weren’t allowed, I’d have to put (at least) one of them
> inside the block, which would be a (minor) pain.
>
> I don’t currently have a very strong opinion about the order of
> evaluation, so I might be convinced otherwise. But combining the two
> clauses is so powerful that I don’t think it’s worth to get rid of just
> because of an edge case.
>
> > It may be workable if you can have only one or the other, but mixing and matching them as proposed above would be a world of hurt:
> >
> > ```
> > for foo in bar where condition1 while condition2 { ... }
> > ```
> >
> > If condition1 and condition2 both evaluate to true, then whether you continue or break would depend on the relative order of where and while; for generality, you would want to allow both `for...in...where...while` and `for...in...while...where`, and likely `for...in...while...where...while`, etc. There is nothing in the meaning of those words that would suggest that `while...where` behaves differently from `where...while`, etc. This is why words like "break" and "continue" are IMO far superior.
> >
> >
> > On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com > > <mailto:erica@ericasadun.com>(mailto:erica@ericasadun.com > > <mailto:erica@ericasadun.com>)>wrote:
> > >
> > > > On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution<swift-evolution@swift.org > > <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org > > <mailto:swift-evolution@swift.org>)>wrote:
> > > > > The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.
> > > >
> > > > It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.
> > >
> > > The where_clause appears in the for in statement
> > >
> > > for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block
> > >
> > > It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):
> > >
> > > for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
> > > when_clause : 'when' expression
> > >
> > > and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.
> > >
> > > I'd say that in both cases, combining chaining and statements is
> marginallyless goodthan either using standalone chaining or statements
> without chaining. But as I say this, I know as a fact, I fully intend
> to use `sequence(_:, next:).take(while:)` with for0in statements, so
> I'm starting from a hypocritical vantage point.
> > >
> > > To summarize, I'm more +0.01 than I am -0.01 on this.
> > >
> > > -- E
> > > p.s. Sorry, wux
>
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Interesting. What if you put newlines before `where` and `while`? It’s
hard to get the spacing right in a mailing list, but I tried it in Xcode
and it looks really good to me (except for the compiler error it currently
produces). Way better than the way I wrote it initially and the
alternatives you mentioned.

for number in fibonacci
    where number % 2 == 0
    while number < 4_000_000 { }

This last line here is indistinguishable from the beginning of a while
loop. I still think my examples above are superior, but even if you don't
want to operate on the sequence beforehand, we can rewrite your multiline
statement inside the loop in a crystal-clear way, no dollar signs or
anything:

for number in fibonacci {
  if number % 2 != 0 { continue }
  if number >= 4_000_000 { break }
}

Now the behavior is written out in full. It has the following advantages:

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.)

2) It is absolutely clear which if statement gets evaluated first. Of
course, we can make a rule for your proposed keyword, but there's no basis
for assuming a priori that such a statement must be evaluated from left to
right without consulting the Swift-specific rulebook. Take, for example,
Python `foo if bar else boo`. By contrast, the if statements shown above
are clearly evaluated one after the other and would be evaluated in the
same order in every language under the sun.

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.

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.

Each new piece of syntax is a challenge, and making connections between two
equivalent facilities can be very, very hard. I've witnessed truly
brilliant people who are starting out to code throw up their hands in
frustration because it feels unnecessarily cruel that they must learn
several synonyms for the same concept. One of them asked me recently, "If I
can write i = i + 1, why would I ever write i += 1 or i++? There must be
something special about ++, surely? Does it have any other uses?" He
concluded that he did not in fact understand assignment operators; I could
not convince him that he understood them perfectly adequately.

Adding sugar for visual elegance carries this cost to the learner, and it
is a real and non-trivial cost. Many beginners, I find, can accept that
they'll read function names that they haven't heard of; after all, they can
see that anyone can make a function named anything. But, a keyword or a
core part of the language's syntax? Please appreciate that every addition
there increases the learning curve for everyone.

Given that so many choices about how to write a loop are already available,
you haven't convinced me that having another one brings tangible benefit to
the language or to the code that I write. By contrast, I would cringe if I
saw something like `for number in fibonacci where number % 2 == 0 while
number<4_000_000 { }` written on one line (and there is an understandable
natural tendency to want to put a single statement all in one line). IMO,
the Swifty way, with its emphasis on not having multiple "dialects" of the
same language, would be to *decrease* the number of ways to write the same
loop to one or a small number of well-considered, generally useful
facilities. That's why I'm in favor of cutting down on sugar rather than
increasing it.

···

On Tue, Jun 7, 2016 at 6:26 PM, Tim Vermeulen <tvermeulen@me.com> wrote:

> On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen<tvermeulen@me.com(mailto: > tvermeulen@me.com)>wrote:
> > I’ve been thinking about this for a bit now, and I think it would make
most sense to evaluate these clauses from left to right. However, cases
where the order matters are very uncommon, and I would rather have the
power to choose which clause is evaluated first than to have a forced
default order. Either way I don’t see this as a reason not to allow
combining the two clauses because IMO it can lead to some very clean code.
For instance, say we want to loop through all even fibonacci numbers below
4 million(see problem #2 from project euler), we could do this:
> >
> > `for number in fibonacci where number % 2 == 0 while number<4_000_000
{ }`
> This statement looks like spaghetti to me. I would not at all support
extending the language to permit it. Do you really think it's more readable
than going step-by-step?
>
> ```
> let numbers = fibonacci.prefix { $0<4_000_000 }
> for number in numbers where number % 2 == 0 {
> // ...
> }
> ```
>
> or just:
>
> ```
> let numbers = fibonacci.prefix { $0<4_000_000 }
> let evens = numbers.filter { $0 % 2 == 0 }
> for number in evens {
> // ...
> }
> ```
>
> >
> > I could have ordered the two clauses in any way I want. If combining
the clauses weren’t allowed, I’d have to put (at least) one of them inside
the block, which would be a (minor) pain.
> >
> > I don’t currently have a very strong opinion about the order of
evaluation, so I might be convinced otherwise. But combining the two
clauses is so powerful that I don’t think it’s worth to get rid of just
because of an edge case.
> >
> > >It may be workable if you can have only one or the other, but mixing
and matching them as proposed above would be a world of hurt:
> > >
> > >```
> > >for foo in bar where condition1 while condition2 { ... }
> > >```
> > >
> > >If condition1 and condition2 both evaluate to true, then whether you
continue or break would depend on the relative order of where and while;
for generality, you would want to allow both `for...in...where...while` and
`for...in...while...where`, and likely `for...in...while...where...while`,
etc. There is nothing in the meaning of those words that would suggest that
`while...where` behaves differently from `where...while`, etc. This is why
words like "break" and "continue" are IMO far superior.
> > >
> > >
> > >On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com > (mailto:erica@ericasadun.com)(mailto:erica@ericasadun.com)>wrote:
> > >>
> > >>>On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution< > swift-evolution@swift.org(mailto:swift-evolution@swift.org)(mailto: > swift-evolution@swift.org)>wrote:
> > >>>>The meaning of the proposed while is not at all a pair for where,
since where clauses in while loops would do the same thing as while clauses
in for loops. That's crazy.
> > >>>
> > >>>It sounds crazy, but it’s the nature of the while loop. A where
clause in a while loop also has a different result than a where clause in a
for loop.
> > >>
> > >>The where_clause appears in the for in statement
> > >>
> > >>for_in_statement : 'for' 'case'? pattern 'in' expression
where_clause? code_block
> > >>
> > >>It's syntactic sugar because the expression can be already be
limited through functional chaining of some sort or another. At the same
time, it's nice and pleasant to have `where` and I'm not itching to throw
it out. The same courtesy could be easily extend to `when` (because I don't
really want to use the `while` keyword here, but I could easily be
convinced otherwise because I don't have a strong stance either way):
> > >>
> > >>for_in_statement : 'for' 'case'? pattern 'in' expression
(where_clause | when_clause)? code_block
> > >>when_clause : 'when' expression
> > >>
> > >>and again it could be nice and pleasant to have, although not
necessary. The question comes down to how much does the language benefit by
this sugar.
> > >>
> > >>I'd say that in both cases, combining chaining and statements is
marginallyless goodthan either using standalone chaining or statements
without chaining. But as I say this, I know as a fact, I fully intend to
use `sequence(_:, next:).take(while:)` with for0in statements, so I'm
starting from a hypocritical vantage point.
> > >>
> > >>To summarize, I'm more +0.01 than I am -0.01 on this.
> > >>
> > >>-- E
> > >>p.s. Sorry, wux
> > >>
> > >>
> > >
> > >
> > >
>
>
>

For most of of this discussion I have been for the introduction of 'while' and against the removal of 'where'; IMO, both help carry the intent of the code a bit better than the un-sugared version using if block (which can be mistaken for a regular condition)

for number in fibonacci
{
if number % 2 == 0 { continue }
if number < 4_000_000 { break }
if number < 10 { print("small:", number) }
else { print("large:", number) }
}

The issue with the 'where' and this new 'while' is that they may not be useable with the 'repeat' and 'while'-loop.

Thinking outside of the box, I was wondering if the 'where'/'while' could be move inside the loop code itself; but without tagging a 'continue' or 'break' it would be too confusing, as too disconnected from the 'for'

for number in fibonacci
{
where number % 2 == 0
while number < 4_000_000
}

And not sure how one could specify the loop label as now being free-standing, they can appear anywhere. So how about 'when ... continue|break' which is just pure sugar

label:
for number in fibonacci
{
when number % 2 == 0 continue label
when number < 4_000_000 break label
}

Not shorter than the 'if' variant, but I'm sure a some on the list would enjoy the curly brace free syntax.

Dany

···

Le 7 juin 2016 à 19:26, Tim Vermeulen via swift-evolution <swift-evolution@swift.org> a écrit :

Interesting. What if you put newlines before `where` and `while`? It’s hard to get the spacing right in a mailing list, but I tried it in Xcode and it looks really good to me (except for the compiler error it currently produces). Way better than the way I wrote it initially and the alternatives you mentioned.

for number in fibonacci
  where number % 2 == 0
  while number < 4_000_000 { }

On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen<tvermeulen@me.com(mailto:tvermeulen@me.com)>wrote:

I’ve been thinking about this for a bit now, and I think it would make most sense to evaluate these clauses from left to right. However, cases where the order matters are very uncommon, and I would rather have the power to choose which clause is evaluated first than to have a forced default order. Either way I don’t see this as a reason not to allow combining the two clauses because IMO it can lead to some very clean code. For instance, say we want to loop through all even fibonacci numbers below 4 million(see problem #2 from project euler), we could do this:

`for number in fibonacci where number % 2 == 0 while number<4_000_000 { }`

This statement looks like spaghetti to me. I would not at all support extending the language to permit it. Do you really think it's more readable than going step-by-step?

let numbers = fibonacci.prefix { $0<4_000_000 }
for number in numbers where number % 2 == 0 {
// ...
}

or just:

let numbers = fibonacci.prefix { $0<4_000_000 }
let evens = numbers.filter { $0 % 2 == 0 }
for number in evens {
// ...
}

I could have ordered the two clauses in any way I want. If combining the clauses weren’t allowed, I’d have to put (at least) one of them inside the block, which would be a (minor) pain.

I don’t currently have a very strong opinion about the order of evaluation, so I might be convinced otherwise. But combining the two clauses is so powerful that I don’t think it’s worth to get rid of just because of an edge case.

It may be workable if you can have only one or the other, but mixing and matching them as proposed above would be a world of hurt:

for foo in bar where condition1 while condition2 { ... }

If condition1 and condition2 both evaluate to true, then whether you continue or break would depend on the relative order of where and while; for generality, you would want to allow both `for...in...where...while` and `for...in...while...where`, and likely `for...in...while...where...while`, etc. There is nothing in the meaning of those words that would suggest that `while...where` behaves differently from `where...while`, etc. This is why words like "break" and "continue" are IMO far superior.

On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com(mailto:erica@ericasadun.com)(mailto:erica@ericasadun.com)>wrote:

On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)(mailto:swift-evolution@swift.org)>wrote:

The meaning of the proposed while is not at all a pair for where, since where clauses in while loops would do the same thing as while clauses in for loops. That's crazy.

It sounds crazy, but it’s the nature of the while loop. A where clause in a while loop also has a different result than a where clause in a for loop.

The where_clause appears in the for in statement

for_in_statement : 'for' 'case'? pattern 'in' expression where_clause? code_block

It's syntactic sugar because the expression can be already be limited through functional chaining of some sort or another. At the same time, it's nice and pleasant to have `where` and I'm not itching to throw it out. The same courtesy could be easily extend to `when` (because I don't really want to use the `while` keyword here, but I could easily be convinced otherwise because I don't have a strong stance either way):

for_in_statement : 'for' 'case'? pattern 'in' expression (where_clause | when_clause)? code_block
when_clause : 'when' expression

and again it could be nice and pleasant to have, although not necessary. The question comes down to how much does the language benefit by this sugar.

I'd say that in both cases, combining chaining and statements is marginallyless goodthan either using standalone chaining or statements without chaining. But as I say this, I know as a fact, I fully intend to use `sequence(_:, next:).take(while:)` with for0in statements, so I'm starting from a hypocritical vantage point.

To summarize, I'm more +0.01 than I am -0.01 on this.

-- E
p.s. Sorry, wux

_______________________________________________
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

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, 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. Chaining methods can do this, but it’s actually less readable IMO, or requires multiple lines to keep it clear which defeats the point.

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. 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.

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.

···

On 8 Jun 2016, at 01:54, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

This is a really strong argument in my opinion. If we don’t add a `while`
to for loops, then in some situations we will have to rewrite a `where`
clause to something potentially less elegant, given that we don’t want to
give up performance.

I disagree. I argue that what you call "less elegant", namely if (or guard)
inside the loop, is the most elegant solution.

···

On Wed, Jun 8, 2016 at 1:35 PM, Tim Vermeulen via swift-evolution < swift-evolution@swift.org> wrote:

> IMO `.prefix` is just not the equal alternative for as proposed `while` :
> in case of 'while' expression `number<4_000_000` will be calculated
> *only* for those who `number % 2 == 0`. In case of `prefix` - the
> expression will be processed for each `number` and only after this
filtered
> by `number % 2`. Let's assume we need to check for some
> veryExpensiveTest(number):
>
> for number in fibonacci where number % 2 == 0 while
> veryExpensiveTest(number) {}
>
> let numbers = fibonacci.prefix { veryExpensiveTest($0) }
> for number in numbers where number % 2 == 0 {}
>
> So, `while` for `for` loops just can't be always replaced with `prefix`
>
> On 08.06.2016 2:02, Xiaodi Wu via swift-evolution wrote:
> > On Tue, Jun 7, 2016 at 5:11 PM, Tim Vermeulen<tvermeulen@me.com > > > <mailto:tvermeulen@me.com>>wrote:
> >
> > I’ve been thinking about this for a bit now, and I think it would make
> > most sense to evaluate these clauses from left to right. However, cases
> > where the order matters are very uncommon, and I would rather have the
> > power to choose which clause is evaluated first than to have a forced
> > default order. Either way I don’t see this as a reason not to allow
> > combining the two clauses because IMO it can lead to some very clean
> > code. For instance, say we want to loop through all even fibonacci
> > numbers below 4 million (see problem #2 from project euler), we could
> > do this:
> >
> > `for number in fibonacci where number % 2 == 0 while number<4_000_000
> > { }`
> >
> >
> > This statement looks like spaghetti to me. I would not at all support
> > extending the language to permit it. Do you really think it's more
readable
> > than going step-by-step?
> >
> > ```
> > let numbers = fibonacci.prefix { $0<4_000_000 }
> > for number in numbers where number % 2 == 0 {
> > // ...
> > }
> > ```
> >
> > or just:
> >
> > ```
> > let numbers = fibonacci.prefix { $0<4_000_000 }
> > let evens = numbers.filter { $0 % 2 == 0 }
> > for number in evens {
> > // ...
> > }
> > ```
> >
> >
> > I could have ordered the two clauses in any way I want. If combining
> > the clauses weren’t allowed, I’d have to put (at least) one of them
> > inside the block, which would be a (minor) pain.
> >
> > I don’t currently have a very strong opinion about the order of
> > evaluation, so I might be convinced otherwise. But combining the two
> > clauses is so powerful that I don’t think it’s worth to get rid of just
> > because of an edge case.
> >
> > > It may be workable if you can have only one or the other, but mixing
and matching them as proposed above would be a world of hurt:
> > >
> > > ```
> > > for foo in bar where condition1 while condition2 { ... }
> > > ```
> > >
> > > If condition1 and condition2 both evaluate to true, then whether you
continue or break would depend on the relative order of where and while;
for generality, you would want to allow both `for...in...where...while` and
`for...in...while...where`, and likely `for...in...while...where...while`,
etc. There is nothing in the meaning of those words that would suggest that
`while...where` behaves differently from `where...while`, etc. This is why
words like "break" and "continue" are IMO far superior.
> > >
> > >
> > > On Tue, Jun 7, 2016 at 2:34 PM, Erica Sadun<erica@ericasadun.com > > > <mailto:erica@ericasadun.com>(mailto:erica@ericasadun.com > > > <mailto:erica@ericasadun.com>)>wrote:
> > > >
> > > > > On Jun 7, 2016, at 1:16 PM, Tim Vermeulen via swift-evolution< > swift-evolution@swift.org > > > <mailto:swift-evolution@swift.org>(mailto:swift-evolution@swift.org > > > <mailto:swift-evolution@swift.org>)>wrote:
> > > > > > The meaning of the proposed while is not at all a pair for
where, since where clauses in while loops would do the same thing as while
clauses in for loops. That's crazy.
> > > > >
> > > > > It sounds crazy, but it’s the nature of the while loop. A where
clause in a while loop also has a different result than a where clause in a
for loop.
> > > >
> > > > The where_clause appears in the for in statement
> > > >
> > > > for_in_statement : 'for' 'case'? pattern 'in' expression
where_clause? code_block
> > > >
> > > > It's syntactic sugar because the expression can be already be
limited through functional chaining of some sort or another. At the same
time, it's nice and pleasant to have `where` and I'm not itching to throw
it out. The same courtesy could be easily extend to `when` (because I don't
really want to use the `while` keyword here, but I could easily be
convinced otherwise because I don't have a strong stance either way):
> > > >
> > > > for_in_statement : 'for' 'case'? pattern 'in' expression
(where_clause | when_clause)? code_block
> > > > when_clause : 'when' expression
> > > >
> > > > and again it could be nice and pleasant to have, although not
necessary. The question comes down to how much does the language benefit by
this sugar.
> > > >
> > > > I'd say that in both cases, combining chaining and statements is
> > marginallyless goodthan either using standalone chaining or statements
> > without chaining. But as I say this, I know as a fact, I fully intend
> > to use `sequence(_:, next:).take(while:)` with for0in statements, so
> > I'm starting from a hypocritical vantage point.
> > > >
> > > > To summarize, I'm more +0.01 than I am -0.01 on this.
> > > >
> > > > -- E
> > > > p.s. Sorry, wux
> >
> >
> >
> >
> > _______________________________________________
> > 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

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".

···

On Wed, Jun 8, 2016 at 3:38 AM, Haravikk <swift-evolution@haravikk.me> wrote:

On 8 Jun 2016, at 01:54, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

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.

So, I think it might be much clearer if, similarly to how there's a
discussion about unifying "where" vs. "comma" conditions in guard/if, we
could do the same here.

    while let value = foo.next(), let something = value.property, something
== 4 { ... }

(Apologies if this has been said; I haven't followed the whole thread
closely.)

···

On Wed, Jun 8, 2016 at 1:38 AM, Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

I’m not sure I agree that this is confusing, 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.

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.

The original sin here was in connecting the `where` clause to the for loop's sequence expression, rather than its pattern. If `where` were positioned right after the loop variable:

  for eachValue where someCondition(eachValue) in theValues { … }

It would be much clearer that `where` constrains the values seen by the loop body.

I'm not sure why the `where` clause was placed where it is. I suspect it has something to do with the `where` clause potentially being more complex than the sequence expression, but I was not in the room where it happened, so that's idle speculation.

···

--
Brent Royal-Gordon
Architechies