[swift-evolution] [Review] SE-0007 Remove C-style for-loops with conditions and incrementers

David Owens II david at owensd.io
Fri Dec 11 11:18:37 CST 2015


> On Dec 11, 2015, at 8:27 AM, Erica Sadun via swift-evolution <swift-evolution at swift.org> wrote:
> 
> As for c-style-for vs while, the two are mechanically convertible.

This is provably false and has been demonstrated, but here is an example of it again: 

    var sum = 0
    for var i = 10 /* expr1 */; i > 0 /* expr2 */; i -= 1 /* expr3 */ {
        if i % 2 == 0 { continue } // statement
        sum += 1                   // statement
    }
    print(sum)


    var sum = 0
    var i = 10 // expr1
    while i > 0 /* expr2 */ {
        if i % 2 == 0 { continue } // statement
        sum += 1                   // statement
        
        i -= 1 // expr3
    }
    print(sum)

It’s not just a mechanical conversion; consideration for early loop-exits and continuations need to be made as well. The rote conversion for the while version above is an infinite loop. Not only that, expr1 now leaks variables into a scope that is no longer contained within the loop. 

> Where heavy performance is not required, for-in is more readable, maintainable, and optimizable to a sufficient extent that I do not see it as a bar to conversion.

This is a pure philosophical difference that I don’t think we’ll agree on. The injection of types are required to make for-in constructs work with the hope that the optimizer can clean all of this up later. This is fundamentally the same claim that C++ makes with it’s zero-cost abstraction. Mike Action has some great talks on YouTube that demonstrate many of the real-world problems he runs into.

Should the for ;; construct be used for all loop iteration? No, I don’t think so. But we shouldn’t make the claim that the while-loop is an equivalent form, because it’s not. Can it be used to mimic the functionality? Of course, but not in a mechanical conversion like you suggest. Care has to be taken that the statements don’t essentially branch and an artificial scope needs to be added. 

    if true {
        var sum = 0
        var i = 10 // expr1
        while i > 0 /* expr2 */ {
            if i % 2 == 0 { continue } // statement
            sum += 1                   // statement
        
            i -= 1 // expr3
        }
    }
    print(sum)

And then there is this:

> Performance is definitely a consideration; we already reverted a pull request that remove C-style fors from the standard library. I believe Andy is currently looking into where the regressions come from. stride(...) performing poorly seems like something we should fix regardless, since that's arguably the idiomatic way to write such loops and ought to perform well. I agree we should investigate ways to ensure common loops over ranges or strides perform reasonably at -Onone if we move forward with this.

-David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151211/cf4b5d38/attachment.html>


More information about the swift-evolution mailing list