Rekindling: "Extending declaration scope to condition for `repeat { } while ()"


(Michael Savich) #1

It recently occurred to me how nice it would be to be if we could avoid declaring variables outside of loops that are only used inside them. I used google’s site specific search (is that the canon way to search swift-evo?) and only found one thread about this, (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/024657.html) where from what I could see it got a positive reception.

It would be a special case though, and within an unrelated thread I saw this suggestion (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001201.html) of letting you write a variable declaration in between the repeat keyword and the opening bracket. Personally I prefer this syntax.

Regardless, I’m wondering what happened to this thread? Is there a reason it didn’t get proposed? If the answer is that the discussion simply died down it may be worth revisiting it.

···

Sent from my Mac


(Xiaodi Wu) #2

If I recall correctly, it was discussed during a time when additive
proposals were not in scope, so it could not be proposed. Since at the
moment we are currently between Swift 4 and Swift 5 evolution, the topic is
not in scope either.

With respect to the idea itself, Taras's post--which appears to be the last
on the subject--is useful to re-consider here:

This is definitively something very useful but it also introduces a

strong asymmetry into Swift statements. In all control-flow statements, the
condition is part of the outer scope. Or, to be more precise, its part of
an intermediate scope between the outer and the inner scope (as you can
declare variables in the condition which are invisible to the outer scope
but visible to the inner scope). Your suggestion essentially moves the
condition of repeat {} while () to the inner scope. I think that the more
complex semantics is not worth the change.

I recall being initially in favor of the idea myself. However, any sort of
change of syntax is a big deal; it will prompt a lot of bikeshedding, and
it will require engineering effort to implement that is sorely needed
elsewhere. With time, I question whether this idea meets the necessarily
high bar for changing syntax; indeed if the motivation is to keep something
from the outer scope, it's trivial to make this happen with an outer `do`:

do {
  var i = 0
  repeat {
    // ...
  } while i < 42
}
···

On Tue, Jun 6, 2017 at 4:05 AM, Michael Savich via swift-evolution < swift-evolution@swift.org> wrote:

It recently occurred to me how nice it would be to be if we could avoid
declaring variables outside of loops that are only used inside them. I used
google’s site specific search (is that the canon way to search swift-evo?)
and only found one thread about this, (https://lists.swift.org/
pipermail/swift-evolution/Week-of-Mon-20160718/024657.html) where from
what I could see it got a positive reception.

It would be a special case though, and within an unrelated thread I saw
this suggestion (https://lists.swift.org/pipermail/swift-evolution/
Week-of-Mon-20151207/001201.html) of letting you write a variable
declaration in between the repeat keyword and the opening bracket.
Personally I prefer this syntax.

Regardless, I’m wondering what happened to this thread? Is there a reason
it didn’t get proposed? If the answer is that the discussion simply died
down it may be worth revisiting it.

Sent from my Mac

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


(Michael Savich) #3

Oh, I admit I had never realized do could be used outside of an error handling context. Yeah, then I would agree then this change is probably unnecessary. Looking at the Swift guidebook it may be a good idea make it more explicit that the do statement is meant to be used for things other than do-try-catch, assuming that this is an intended use case. But I digress, as that would be a discussion for another time/thread.

···

Sent from my Mac

On Jun 6, 2017, at 6:52 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If I recall correctly, it was discussed during a time when additive proposals were not in scope, so it could not be proposed. Since at the moment we are currently between Swift 4 and Swift 5 evolution, the topic is not in scope either.

With respect to the idea itself, Taras's post--which appears to be the last on the subject--is useful to re-consider here:

> This is definitively something very useful but it also introduces a strong asymmetry into Swift statements. In all control-flow statements, the condition is part of the outer scope. Or, to be more precise, its part of an intermediate scope between the outer and the inner scope (as you can declare variables in the condition which are invisible to the outer scope but visible to the inner scope). Your suggestion essentially moves the condition of repeat {} while () to the inner scope. I think that the more complex semantics is not worth the change.

I recall being initially in favor of the idea myself. However, any sort of change of syntax is a big deal; it will prompt a lot of bikeshedding, and it will require engineering effort to implement that is sorely needed elsewhere. With time, I question whether this idea meets the necessarily high bar for changing syntax; indeed if the motivation is to keep something from the outer scope, it's trivial to make this happen with an outer `do`:

do {
  var i = 0
  repeat {
    // ...
  } while i < 42
}

On Tue, Jun 6, 2017 at 4:05 AM, Michael Savich via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
It recently occurred to me how nice it would be to be if we could avoid declaring variables outside of loops that are only used inside them. I used google’s site specific search (is that the canon way to search swift-evo?) and only found one thread about this, (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/024657.html) where from what I could see it got a positive reception.

It would be a special case though, and within an unrelated thread I saw this suggestion (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001201.html) of letting you write a variable declaration in between the repeat keyword and the opening bracket. Personally I prefer this syntax.

Regardless, I’m wondering what happened to this thread? Is there a reason it didn’t get proposed? If the answer is that the discussion simply died down it may be worth revisiting it.

Sent from my Mac

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


(Dave Abrahams) #4

It recently occurred to me how nice it would be to be if we could avoid
declaring variables outside of loops that are only used inside them. I used
google’s site specific search (is that the canon way to search swift-evo?)
and only found one thread about this, (https://lists.swift.org/
pipermail/swift-evolution/Week-of-Mon-20160718/024657.html) where from
what I could see it got a positive reception.

IMO this is a language design bug of the sort that makes itself
glaringly obvious after only a few uses of the feature in question. It
frustrates me that we haven't fixed it yet.

If I recall correctly, it was discussed during a time when additive
proposals were not in scope, so it could not be proposed. Since at the
moment we are currently between Swift 4 and Swift 5 evolution, the topic is
not in scope either.

With respect to the idea itself, Taras's post--which appears to be the last
on the subject--is useful to re-consider here:

This is definitively something very useful but it also introduces a
strong asymmetry into Swift statements. In all control-flow statements, the
condition is part of the outer scope. Or, to be more precise, its part of
an intermediate scope between the outer and the inner scope (as you can
declare variables in the condition which are invisible to the outer scope
but visible to the inner scope). Your suggestion essentially moves the
condition of repeat {} while () to the inner scope. I think that the more
complex semantics is not worth the change.

I find that argument unconvincing, personally. Even if the condition in

  while condition {...}

was “part of the inner scope,” it would be a distinction without a
difference, because you can't refer to a local variable before its
declaration, and the declaration of anything in the inner scope must
follow the condition.

I recall being initially in favor of the idea myself. However, any sort of
change of syntax is a big deal; it will prompt a lot of bikeshedding, and
it will require engineering effort to implement that is sorely needed
elsewhere. With time, I question whether this idea meets the necessarily
high bar for changing syntax; indeed if the motivation is to keep something
from the outer scope, it's trivial to make this happen with an outer `do`:

do {
  var i = 0
  repeat {
    // ...
  } while i < 42
}

Don't you gag a little every time you have to add levels of nesting,
initialize variables twice, or separate declarations from
initializations as a workaround? I do.

I'd rather not do this with extra syntax, myself. The change in
semantics in the rare case where a variable is shadowed inside a loop
body *and* used in a trailing condition can be handled with warnings and
migration.

···

On Tue, Jun 6, 2017 at 4:05 AM, Michael Savich via swift-evolution < > swift-evolution@swift.org> wrote:

on Tue Jun 06 2017, Xiaodi Wu <swift-evolution@swift.org> wrote:

--
-Dave


(Xiaodi Wu) #5

>
>> It recently occurred to me how nice it would be to be if we could avoid
>> declaring variables outside of loops that are only used inside them. I
used
>> google’s site specific search (is that the canon way to search
swift-evo?)
>> and only found one thread about this, (https://lists.swift.org/
>> pipermail/swift-evolution/Week-of-Mon-20160718/024657.html) where from
>> what I could see it got a positive reception.

IMO this is a language design bug of the sort that makes itself
glaringly obvious after only a few uses of the feature in question. It
frustrates me that we haven't fixed it yet.

> If I recall correctly, it was discussed during a time when additive
> proposals were not in scope, so it could not be proposed. Since at the
> moment we are currently between Swift 4 and Swift 5 evolution, the topic
is
> not in scope either.
>
> With respect to the idea itself, Taras's post--which appears to be the
last
> on the subject--is useful to re-consider here:
>
>> This is definitively something very useful but it also introduces a
>> strong asymmetry into Swift statements. In all control-flow statements,
the
>> condition is part of the outer scope. Or, to be more precise, its part
of
>> an intermediate scope between the outer and the inner scope (as you can
>> declare variables in the condition which are invisible to the outer
scope
>> but visible to the inner scope). Your suggestion essentially moves the
>> condition of repeat {} while () to the inner scope. I think that the
more
>> complex semantics is not worth the change.

I find that argument unconvincing, personally. Even if the condition in

  while condition {...}

was “part of the inner scope,” it would be a distinction without a
difference, because you can't refer to a local variable before its
declaration, and the declaration of anything in the inner scope must
follow the condition.

>>
>
> I recall being initially in favor of the idea myself. However, any sort
of
> change of syntax is a big deal; it will prompt a lot of bikeshedding, and
> it will require engineering effort to implement that is sorely needed
> elsewhere. With time, I question whether this idea meets the necessarily
> high bar for changing syntax; indeed if the motivation is to keep
something
> from the outer scope, it's trivial to make this happen with an outer
`do`:
>
> ```
> do {
> var i = 0
> repeat {
> // ...
> } while i < 42
> }
> ```

Don't you gag a little every time you have to add levels of nesting,
initialize variables twice, or separate declarations from
initializations as a workaround? I do.

Fair point.

I'd rather not do this with extra syntax, myself.

Right. My personal opinion today is really that if it's something that
requires bikeshedding or extensive engineering, I'd rather not insist on
it. But if it's something that can just happen, it's a nice-to-have.

The change in
semantics in the rare case where a variable is shadowed inside a loop
body *and* used in a trailing condition can be handled with warnings and
migration.

Right, and migrating those cases *could* reveal and resolve unintentional
errors too.

···

On Tue, Jun 6, 2017 at 12:17 PM, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

> On Tue, Jun 6, 2017 at 4:05 AM, Michael Savich via swift-evolution < > > swift-evolution@swift.org> wrote:
on Tue Jun 06 2017, Xiaodi Wu <swift-evolution@swift.org> wrote:


(Haravikk) #6

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

···

On 6 Jun 2017, at 18:45, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Tue, Jun 6, 2017 at 12:17 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> On Tue, Jun 6, 2017 at 4:05 AM, Michael Savich via swift-evolution < > > swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
>> It recently occurred to me how nice it would be to be if we could avoid
>> declaring variables outside of loops that are only used inside them. I used
>> google’s site specific search (is that the canon way to search swift-evo?)
>> and only found one thread about this, (https://lists.swift.org/
>> pipermail/swift-evolution/Week-of-Mon-20160718/024657.html) where from
>> what I could see it got a positive reception.

IMO this is a language design bug of the sort that makes itself
glaringly obvious after only a few uses of the feature in question. It
frustrates me that we haven't fixed it yet.

on Tue Jun 06 2017, Xiaodi Wu <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> If I recall correctly, it was discussed during a time when additive
> proposals were not in scope, so it could not be proposed. Since at the
> moment we are currently between Swift 4 and Swift 5 evolution, the topic is
> not in scope either.
>
> With respect to the idea itself, Taras's post--which appears to be the last
> on the subject--is useful to re-consider here:
>
>> This is definitively something very useful but it also introduces a
>> strong asymmetry into Swift statements. In all control-flow statements, the
>> condition is part of the outer scope. Or, to be more precise, its part of
>> an intermediate scope between the outer and the inner scope (as you can
>> declare variables in the condition which are invisible to the outer scope
>> but visible to the inner scope). Your suggestion essentially moves the
>> condition of repeat {} while () to the inner scope. I think that the more
>> complex semantics is not worth the change.

I find that argument unconvincing, personally. Even if the condition in

  while condition {...}

was “part of the inner scope,” it would be a distinction without a
difference, because you can't refer to a local variable before its
declaration, and the declaration of anything in the inner scope must
follow the condition.

>>
>
> I recall being initially in favor of the idea myself. However, any sort of
> change of syntax is a big deal; it will prompt a lot of bikeshedding, and
> it will require engineering effort to implement that is sorely needed
> elsewhere. With time, I question whether this idea meets the necessarily
> high bar for changing syntax; indeed if the motivation is to keep something
> from the outer scope, it's trivial to make this happen with an outer `do`:
>
> ```
> do {
> var i = 0
> repeat {
> // ...
> } while i < 42
> }
> ```

Don't you gag a little every time you have to add levels of nesting,
initialize variables twice, or separate declarations from
initializations as a workaround? I do.

Fair point.

I'd rather not do this with extra syntax, myself.

Right. My personal opinion today is really that if it's something that requires bikeshedding or extensive engineering, I'd rather not insist on it. But if it's something that can just happen, it's a nice-to-have.

The change in
semantics in the rare case where a variable is shadowed inside a loop
body *and* used in a trailing condition can be handled with warnings and
migration.

Right, and migrating those cases *could* reveal and resolve unintentional errors too.

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


(Haravikk) #7

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!


(Gor Gyolchanyan) #8

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

···

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

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


(Goffredo Marocchi) #9

Quite interesting :), what impact would it have on the compiler?

···

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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


(Gor Gyolchanyan) #10

Not much, I think. The `where` clause already exists, conditional `let` and `var` binding already exists. It'd take loosening up conditional binding rules a bit and expanding the lexical structure to include `let` and `var` bindings in `repeat`.

···

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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


(Xiaodi Wu) #11

_Every_ addition to the basic syntax of the language is, by definition,
high cost. The bar for additions to the standard library is already very
high; the bar for additions to control flow syntax would be extraordinarily
high.

The proposed use case here is far from the original topic of repeat {}
while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the
condition, these live in a magical middle scope that is intuitive to use
but also an exception to the rule of thumb that scopes are surrounded by
braces. As I wrote earlier, it is possible to manually create an analogous
scope by surrounding any loop with do {}. Any addition to the language
would have to be vastly superior to this currently possible alternative,
and I seriously doubt it is possible to invent such a thing because
anything shorter than the four letters in “do {}” would also obscure the
existence of the middle scope being created.

···

On Sat, Jun 10, 2017 at 08:05 Goffredo Marocchi via swift-evolution < swift-evolution@swift.org> wrote:

If it is low cost and people do not come up with regressions/high cost +
negative impact scenarios then I would say go full steam ahead. It does
address an annoying scenario.

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Not much, I think. The `where` clause already exists, conditional `let`
and `var` binding already exists. It'd take loosening up conditional
binding rules a bit and expanding the lexical structure to include `let`
and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution < > swift-evolution@swift.org> wrote:

I think a better way of achieving this would be to use the already
existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow
`let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
if nonoptional >= 10 {
optional = nil
}
optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to
allow any `let` and `var` bindings in conditional scopes without them
contributing to the condition itself:

while let a = 0, a < 10 {
a += 1
print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
a += 1
print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition,
this would be a less invasive and more intuitive way of achieving what you
want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution < > swift-evolution@swift.org> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out;
one other benefit if we ever move to a proper message board is we might
gain the ability to bump topics. Anyway, I'll resend my message just in
case:

Just to add my thoughts, as I like the idea of adding the variables to the
start somehow, but was wondering if might make sense to have a keyword such
as "using", but allow it on all block statements, like-so:

// Original use-case of repeat … while
repeat using (var i = 0) {
// Do something
} while (i < 20)

// for … in demonstrating combination of using and where
for eachItem in theItems using (var i = 0) where (i < 20) {
// Do something either until theItems run out or i reaches 20
}

// Standard while loop
while let eachItem = it.next() using (var i = 0) where (i < 20) {
// As above, but with an iterator and a while loop and conditional binding
to also stop on nil
}

// Closure with its own captured variable
let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

// If statements as well
if somethingIsTrue() using (var i = 0) where (i < 20) {
// Do something
}

// Or even a do block; while it does nothing functionally new, I quite
like it aesthetically
do using (var i = 0) {
// Do something
}

Unifying principle here is that anything created in the using clause
belongs to the loop, conditional branch etc. only, but exists outside the
block itself (thus persisting in the case of loops and closures). I quite
like the possible interaction with where clauses here as a means to avoid
simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common
inner and outer boilerplate, as well as reducing pollution from throwaway
variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring
the captured variable externally, but I'm not convinced that having using
on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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

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


(Goffredo Marocchi) #12

If it is low cost and people do not come up with regressions/high cost + negative impact scenarios then I would say go full steam ahead. It does address an annoying scenario.

···

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Not much, I think. The `where` clause already exists, conditional `let` and `var` binding already exists. It'd take loosening up conditional binding rules a bit and expanding the lexical structure to include `let` and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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


(Gor Gyolchanyan) #13

Yeah, that's why I mentioned a big **if** at the end. I love the `do { }` construct or variable isolation purposes and logical grouping, but unfortunately, Swift 4 has made it a lot uglier, by making it an error in its current form:

do {
  let a = "123"
  print(a)
} // error: missing `while`, also use `repeat` instead

The workaround is to do this:

do {
  let a = "123"
  print(a)
};

It might seem like a little change, but this really really bugs me for some reason. I always felt like semicolons in Swift should never be mandatory and should only be used for writing multiple statements on the same line.

Overall, I agree that this isn't a big enough reason to change the syntax for. Let's just make the `do { }` great again instead.

···

On Jun 10, 2017, at 3:33 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

_Every_ addition to the basic syntax of the language is, by definition, high cost. The bar for additions to the standard library is already very high; the bar for additions to control flow syntax would be extraordinarily high.

The proposed use case here is far from the original topic of repeat {} while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the condition, these live in a magical middle scope that is intuitive to use but also an exception to the rule of thumb that scopes are surrounded by braces. As I wrote earlier, it is possible to manually create an analogous scope by surrounding any loop with do {}. Any addition to the language would have to be vastly superior to this currently possible alternative, and I seriously doubt it is possible to invent such a thing because anything shorter than the four letters in “do {}” would also obscure the existence of the middle scope being created.

On Sat, Jun 10, 2017 at 08:05 Goffredo Marocchi via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
If it is low cost and people do not come up with regressions/high cost + negative impact scenarios then I would say go full steam ahead. It does address an annoying scenario.

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Not much, I think. The `where` clause already exists, conditional `let` and `var` binding already exists. It'd take loosening up conditional binding rules a bit and expanding the lexical structure to include `let` and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com <mailto:panajev@gmail.com>> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #14

The problem with nesting within do {} blocks is that it actually makes the problem worse; the main benefit of being able to declare the variables more conveniently is to eliminate common boiler-plate around loops. Creating them with a limited scope is a useful bonus (and further reduces clutter/name pollution).

On the issue of tackling boilerplate, consider something like the following:

// Remove the first 100+ units of items and store the names in an array
var theNames:[String] = []
do {
var theTotal = 0
while let eachItem = theIterator.next() {
  theNames.append(eachItem.name)
  theTotal += eachItem.value
  if theTotal >= 100 { break }
}
}

With the ability to specify throwaway variables more easily, I'm sticking with my using syntax here:

var theNames:[String] = []
while let eachItem = theIterator.next() using (var theTotal = 0) where (theTotal < 100) {
  theNames.append(eachItem.name)
  theTotal += eachItem.value
}

Depending upon your preference on how to structure the using and where parts this is shorter and easier.

In terms of purely creating throwaway variables, it could be condensed a bit further if we stole anonymous variables from the closure syntax like so:

var theNames:[String] = []
while let eachItem = theIterator.next() using $0 = 0 where $0 < 100 { // $0 is created for this block only
  theNames.append(eachItem.name)
  $0 += eachItem.value
}

In other words, we'd treat $0 = 0 as a shorthand for var foo = 0 on the basis that it's being used for a limited scope (i.e- it's always an initialisation within the using clause, rather than an assignment). This should be consistent with closures on the basis that closures have implicitly created the variables for you.

···

On 10 Jun 2017, at 13:33, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

_Every_ addition to the basic syntax of the language is, by definition, high cost. The bar for additions to the standard library is already very high; the bar for additions to control flow syntax would be extraordinarily high.

The proposed use case here is far from the original topic of repeat {} while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the condition, these live in a magical middle scope that is intuitive to use but also an exception to the rule of thumb that scopes are surrounded by braces. As I wrote earlier, it is possible to manually create an analogous scope by surrounding any loop with do {}. Any addition to the language would have to be vastly superior to this currently possible alternative, and I seriously doubt it is possible to invent such a thing because anything shorter than the four letters in “do {}” would also obscure the existence of the middle scope being created.


(Xiaodi Wu) #15

I did not realize that change occurred with `do {}`! That seems like it
should be a regression, given that previously there was explicitly a fix-it
to rewrite naked `{}` to `do {}`.

···

On Sat, Jun 10, 2017 at 09:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Yeah, that's why I mentioned a big **if** at the end. I love the `do { }`
construct or variable isolation purposes and logical grouping, but
unfortunately, Swift 4 has made it a lot uglier, by making it an error in
its current form:

do {
let a = "123"
print(a)
} // error: missing `while`, also use `repeat` instead

The workaround is to do this:

do {
let a = "123"
print(a)
};

It might seem like a little change, but this really really bugs me for
some reason. I always felt like semicolons in Swift should never be
mandatory and should only be used for writing multiple statements on the
same line.

Overall, I agree that this isn't a big enough reason to change the syntax
for. Let's just make the `do { }` great again instead.

On Jun 10, 2017, at 3:33 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

_Every_ addition to the basic syntax of the language is, by definition,
high cost. The bar for additions to the standard library is already very
high; the bar for additions to control flow syntax would be extraordinarily
high.

The proposed use case here is far from the original topic of repeat {}
while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the
condition, these live in a magical middle scope that is intuitive to use
but also an exception to the rule of thumb that scopes are surrounded by
braces. As I wrote earlier, it is possible to manually create an analogous
scope by surrounding any loop with do {}. Any addition to the language
would have to be vastly superior to this currently possible alternative,
and I seriously doubt it is possible to invent such a thing because
anything shorter than the four letters in “do {}” would also obscure the
existence of the middle scope being created.

On Sat, Jun 10, 2017 at 08:05 Goffredo Marocchi via swift-evolution < > swift-evolution@swift.org> wrote:

If it is low cost and people do not come up with regressions/high cost +
negative impact scenarios then I would say go full steam ahead. It does
address an annoying scenario.

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Not much, I think. The `where` clause already exists, conditional `let`
and `var` binding already exists. It'd take loosening up conditional
binding rules a bit and expanding the lexical structure to include `let`
and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution < >> swift-evolution@swift.org> wrote:

I think a better way of achieving this would be to use the already
existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not
allow `let` and `var` bindings in it, so I'd suggest we add ability to do
that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
if nonoptional >= 10 {
optional = nil
}
optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to
allow any `let` and `var` bindings in conditional scopes without them
contributing to the condition itself:

while let a = 0, a < 10 {
a += 1
print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
a += 1
print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition,
this would be a less invasive and more intuitive way of achieving what you
want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution < >> swift-evolution@swift.org> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled
out; one other benefit if we ever move to a proper message board is we
might gain the ability to bump topics. Anyway, I'll resend my message just
in case:

Just to add my thoughts, as I like the idea of adding the variables to
the start somehow, but was wondering if might make sense to have a keyword
such as "using", but allow it on all block statements, like-so:

// Original use-case of repeat … while
repeat using (var i = 0) {
// Do something
} while (i < 20)

// for … in demonstrating combination of using and where
for eachItem in theItems using (var i = 0) where (i < 20) {
// Do something either until theItems run out or i reaches 20
}

// Standard while loop
while let eachItem = it.next() using (var i = 0) where (i < 20) {
// As above, but with an iterator and a while loop and conditional
binding to also stop on nil
}

// Closure with its own captured variable
let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

// If statements as well
if somethingIsTrue() using (var i = 0) where (i < 20) {
// Do something
}

// Or even a do block; while it does nothing functionally new, I quite
like it aesthetically
do using (var i = 0) {
// Do something
}

Unifying principle here is that anything created in the using clause
belongs to the loop, conditional branch etc. only, but exists outside the
block itself (thus persisting in the case of loops and closures). I quite
like the possible interaction with where clauses here as a means to avoid
simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common
inner and outer boilerplate, as well as reducing pollution from throwaway
variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring
the captured variable externally, but I'm not convinced that having using
on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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

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


(Gor Gyolchanyan) #16

Yeah. So, what's the official process for these kinds of things? I imagine it would warrant a full-fledged proposal, would it?

···

On Jun 10, 2017, at 4:26 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I did not realize that change occurred with `do {}`! That seems like it should be a regression, given that previously there was explicitly a fix-it to rewrite naked `{}` to `do {}`.
On Sat, Jun 10, 2017 at 09:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Yeah, that's why I mentioned a big **if** at the end. I love the `do { }` construct or variable isolation purposes and logical grouping, but unfortunately, Swift 4 has made it a lot uglier, by making it an error in its current form:

do {
  let a = "123"
  print(a)
} // error: missing `while`, also use `repeat` instead

The workaround is to do this:

do {
  let a = "123"
  print(a)
};

It might seem like a little change, but this really really bugs me for some reason. I always felt like semicolons in Swift should never be mandatory and should only be used for writing multiple statements on the same line.

Overall, I agree that this isn't a big enough reason to change the syntax for. Let's just make the `do { }` great again instead.

On Jun 10, 2017, at 3:33 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

_Every_ addition to the basic syntax of the language is, by definition, high cost. The bar for additions to the standard library is already very high; the bar for additions to control flow syntax would be extraordinarily high.

The proposed use case here is far from the original topic of repeat {} while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the condition, these live in a magical middle scope that is intuitive to use but also an exception to the rule of thumb that scopes are surrounded by braces. As I wrote earlier, it is possible to manually create an analogous scope by surrounding any loop with do {}. Any addition to the language would have to be vastly superior to this currently possible alternative, and I seriously doubt it is possible to invent such a thing because anything shorter than the four letters in “do {}” would also obscure the existence of the middle scope being created.

On Sat, Jun 10, 2017 at 08:05 Goffredo Marocchi via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
If it is low cost and people do not come up with regressions/high cost + negative impact scenarios then I would say go full steam ahead. It does address an annoying scenario.

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Not much, I think. The `where` clause already exists, conditional `let` and `var` binding already exists. It'd take loosening up conditional binding rules a bit and expanding the lexical structure to include `let` and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com <mailto:panajev@gmail.com>> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Pavol Vaskovic) #17

I think you just reinvented the C-style for loop, that was removed in
SE-0007
<https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md>
.

--Pavol

···

On Sun, Jun 11, 2017 at 1:52 AM, Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

With the ability to specify throwaway variables more easily, I'm sticking
with my using syntax here:

var theNames:[String] = []
while let eachItem = theIterator.next() using (var theTotal = 0) where
(theTotal < 100) {
theNames.append(eachItem.name)
theTotal += eachItem.value
}

Depending upon your preference on how to structure the using and where
parts this is shorter and easier.


(Xiaodi Wu) #18

Well, IMO, if that change was intentional, it’s the original change that
warrants a full-fledged proposal. Without it, I think it’d be justified to
call this a regression and file a bug!

···

On Sat, Jun 10, 2017 at 09:29 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Yeah. So, what's the official process for these kinds of things? I imagine
it would warrant a full-fledged proposal, would it?

On Jun 10, 2017, at 4:26 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I did not realize that change occurred with `do {}`! That seems like it
should be a regression, given that previously there was explicitly a fix-it
to rewrite naked `{}` to `do {}`.
On Sat, Jun 10, 2017 at 09:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Yeah, that's why I mentioned a big **if** at the end. I love the `do { }`
construct or variable isolation purposes and logical grouping, but
unfortunately, Swift 4 has made it a lot uglier, by making it an error in
its current form:

do {
let a = "123"
print(a)
} // error: missing `while`, also use `repeat` instead

The workaround is to do this:

do {
let a = "123"
print(a)
};

It might seem like a little change, but this really really bugs me for
some reason. I always felt like semicolons in Swift should never be
mandatory and should only be used for writing multiple statements on the
same line.

Overall, I agree that this isn't a big enough reason to change the syntax
for. Let's just make the `do { }` great again instead.

On Jun 10, 2017, at 3:33 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

_Every_ addition to the basic syntax of the language is, by definition,
high cost. The bar for additions to the standard library is already very
high; the bar for additions to control flow syntax would be extraordinarily
high.

The proposed use case here is far from the original topic of repeat {}
while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the
condition, these live in a magical middle scope that is intuitive to use
but also an exception to the rule of thumb that scopes are surrounded by
braces. As I wrote earlier, it is possible to manually create an analogous
scope by surrounding any loop with do {}. Any addition to the language
would have to be vastly superior to this currently possible alternative,
and I seriously doubt it is possible to invent such a thing because
anything shorter than the four letters in “do {}” would also obscure the
existence of the middle scope being created.

On Sat, Jun 10, 2017 at 08:05 Goffredo Marocchi via swift-evolution < >> swift-evolution@swift.org> wrote:

If it is low cost and people do not come up with regressions/high cost +
negative impact scenarios then I would say go full steam ahead. It does
address an annoying scenario.

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Not much, I think. The `where` clause already exists, conditional `let`
and `var` binding already exists. It'd take loosening up conditional
binding rules a bit and expanding the lexical structure to include `let`
and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com> >>> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution < >>> swift-evolution@swift.org> wrote:

I think a better way of achieving this would be to use the already
existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not
allow `let` and `var` bindings in it, so I'd suggest we add ability to do
that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
if nonoptional >= 10 {
optional = nil
}
optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to
allow any `let` and `var` bindings in conditional scopes without them
contributing to the condition itself:

while let a = 0, a < 10 {
a += 1
print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
a += 1
print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition,
this would be a less invasive and more intuitive way of achieving what you
want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution < >>> swift-evolution@swift.org> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled
out; one other benefit if we ever move to a proper message board is we
might gain the ability to bump topics. Anyway, I'll resend my message just
in case:

Just to add my thoughts, as I like the idea of adding the variables to
the start somehow, but was wondering if might make sense to have a keyword
such as "using", but allow it on all block statements, like-so:

// Original use-case of repeat … while
repeat using (var i = 0) {
// Do something
} while (i < 20)

// for … in demonstrating combination of using and where
for eachItem in theItems using (var i = 0) where (i < 20) {
// Do something either until theItems run out or i reaches 20
}

// Standard while loop
while let eachItem = it.next() using (var i = 0) where (i < 20) {
// As above, but with an iterator and a while loop and conditional
binding to also stop on nil
}

// Closure with its own captured variable
let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

// If statements as well
if somethingIsTrue() using (var i = 0) where (i < 20) {
// Do something
}

// Or even a do block; while it does nothing functionally new, I quite
like it aesthetically
do using (var i = 0) {
// Do something
}

Unifying principle here is that anything created in the using clause
belongs to the loop, conditional branch etc. only, but exists outside the
block itself (thus persisting in the case of loops and closures). I quite
like the possible interaction with where clauses here as a means to avoid
simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common
inner and outer boilerplate, as well as reducing pollution from throwaway
variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring
the captured variable externally, but I'm not convinced that having using
on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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

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


(Gor Gyolchanyan) #19

Judging by the fact that the error says something like "missing `while`" and "use `repeat`instead", it looks like a bug in the parser, where it goes with the `do-while` to `repeat-while` transition error before checking for other possible constructs like `do { }`.

···

On Jun 10, 2017, at 4:30 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Well, IMO, if that change was intentional, it’s the original change that warrants a full-fledged proposal. Without it, I think it’d be justified to call this a regression and file a bug!
On Sat, Jun 10, 2017 at 09:29 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Yeah. So, what's the official process for these kinds of things? I imagine it would warrant a full-fledged proposal, would it?

On Jun 10, 2017, at 4:26 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

I did not realize that change occurred with `do {}`! That seems like it should be a regression, given that previously there was explicitly a fix-it to rewrite naked `{}` to `do {}`.
On Sat, Jun 10, 2017 at 09:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Yeah, that's why I mentioned a big **if** at the end. I love the `do { }` construct or variable isolation purposes and logical grouping, but unfortunately, Swift 4 has made it a lot uglier, by making it an error in its current form:

do {
  let a = "123"
  print(a)
} // error: missing `while`, also use `repeat` instead

The workaround is to do this:

do {
  let a = "123"
  print(a)
};

It might seem like a little change, but this really really bugs me for some reason. I always felt like semicolons in Swift should never be mandatory and should only be used for writing multiple statements on the same line.

Overall, I agree that this isn't a big enough reason to change the syntax for. Let's just make the `do { }` great again instead.

On Jun 10, 2017, at 3:33 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

_Every_ addition to the basic syntax of the language is, by definition, high cost. The bar for additions to the standard library is already very high; the bar for additions to control flow syntax would be extraordinarily high.

The proposed use case here is far from the original topic of repeat {} while, which is unique because the condition lexically follows the loop.

For those loops in Swift where it is possible to declare variables in the condition, these live in a magical middle scope that is intuitive to use but also an exception to the rule of thumb that scopes are surrounded by braces. As I wrote earlier, it is possible to manually create an analogous scope by surrounding any loop with do {}. Any addition to the language would have to be vastly superior to this currently possible alternative, and I seriously doubt it is possible to invent such a thing because anything shorter than the four letters in “do {}” would also obscure the existence of the middle scope being created.

On Sat, Jun 10, 2017 at 08:05 Goffredo Marocchi via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
If it is low cost and people do not come up with regressions/high cost + negative impact scenarios then I would say go full steam ahead. It does address an annoying scenario.

Sent from my iPhone

On 10 Jun 2017, at 12:04, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Not much, I think. The `where` clause already exists, conditional `let` and `var` binding already exists. It'd take loosening up conditional binding rules a bit and expanding the lexical structure to include `let` and `var` bindings in `repeat`.

On Jun 10, 2017, at 2:01 PM, Goffredo Marocchi <panajev@gmail.com <mailto:panajev@gmail.com>> wrote:

Quite interesting :), what impact would it have on the compiler?

Sent from my iPhone

On 10 Jun 2017, at 11:46, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I think a better way of achieving this would be to use the already existing `where` keyword in loops. The way it works right now is as follows:

let many = [1, 2, 3, 4, 5]
for each in many where each % 2 == 0 {
  print("found an even number: \(each)")
}

Unfortunately, unlike all other conditional scopes, `where` does not allow `let` and `var` bindings in it, so I'd suggest we add ability to do that:

let many: [Int?] = [1, 2, nil, 3, 4, nil, 5]
for each in many where let number = each {
  print("found a non-nil number: \(number)")
}

Or, more interestingly:

for each in many where let number = each, number % 2 == 0 {
  print("found a non-nil even number: \(number)")
}

And in case of a while loop:

var optional: Int? = 1
while let nonoptional = optional {
  if nonoptional >= 10 {
    optional = nil
  }
  optional = nonoptional + 1
}

But this is only for optional unpacking, so another addition would be to allow any `let` and `var` bindings in conditional scopes without them contributing to the condition itself:

while let a = 0, a < 10 {
  a += 1
  print(a)
}

And finally, allow these bindings in `repeat`:

repeat let a = 0 {
  a += 1
  print(0)
} while a < 10

I think **if** the core team would consider this a worthwhile addition, this would be a less invasive and more intuitive way of achieving what you want.

On Jun 10, 2017, at 1:31 PM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Not sure if my e-mail didn't go through or if discussion just fizzled out; one other benefit if we ever move to a proper message board is we might gain the ability to bump topics. Anyway, I'll resend my message just in case:

Just to add my thoughts, as I like the idea of adding the variables to the start somehow, but was wondering if might make sense to have a keyword such as "using", but allow it on all block statements, like-so:

  // Original use-case of repeat … while
  repeat using (var i = 0) {
    // Do something
  } while (i < 20)

  // for … in demonstrating combination of using and where
  for eachItem in theItems using (var i = 0) where (i < 20) {
    // Do something either until theItems run out or i reaches 20
  }

  // Standard while loop
  while let eachItem = it.next() using (var i = 0) where (i < 20) {
    // As above, but with an iterator and a while loop and conditional binding to also stop on nil
  }

  // Closure with its own captured variable
  let myClosure:(Int) -> Int = using (var i = 0) { i += 1; return i * $0 }

  // If statements as well
  if somethingIsTrue() using (var i = 0) where (i < 20) {
    // Do something
  }

  // Or even a do block; while it does nothing functionally new, I quite like it aesthetically
  do using (var i = 0) {
    // Do something
  }

Unifying principle here is that anything created in the using clause belongs to the loop, conditional branch etc. only, but exists outside the block itself (thus persisting in the case of loops and closures). I quite like the possible interaction with where clauses here as a means to avoid simple inner conditionals as well.

Basically the two clauses can work nicely together to avoid some common inner and outer boilerplate, as well as reducing pollution from throwaway variables.

Only one I'm a bit iffy on is the closure; I'm trying to avoid declaring the captured variable externally, but I'm not convinced that having using on its own is clear enough?

Anyway, just an idea!

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Sweeris) #20

Eh, as long as a feature wasn’t removed for security or correctness reasons (which isn’t the case with SE-0007), I don’t see a problem with one proposal enabling functionality that was removed by another. It’s not like we said C-style for loops are evil or anything, just that they weren’t right for Swift. If it turns out that something which otherwise is right for Swift can be “abused” to get C-style for loop semantics, then those who voted against SE-0007 are free to try out this new syntax and see if that helps them. IMHO, anyway.

- Dave Sweeris

···

On Jun 12, 2017, at 5:13 PM, Pavol Vaskovic via swift-evolution <swift-evolution@swift.org> wrote:

On Sun, Jun 11, 2017 at 1:52 AM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

With the ability to specify throwaway variables more easily, I'm sticking with my using syntax here:

var theNames:[String] = []
while let eachItem = theIterator.next() using (var theTotal = 0) where (theTotal < 100) {
  theNames.append(eachItem.name)
  theTotal += eachItem.value
}

Depending upon your preference on how to structure the using and where parts this is shorter and easier.

I think you just reinvented the C-style for loop, that was removed in SE-0007 <https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md>.