[swift-evolution] Rekindling: "Extending declaration scope to condition for `repeat { } while ()"

Haravikk swift-evolution at haravikk.me
Sat Jun 10 18:52:12 CDT 2017


> On 10 Jun 2017, at 13:33, Xiaodi Wu via swift-evolution <swift-evolution at 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.

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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170611/463326fa/attachment.html>


More information about the swift-evolution mailing list