Swift replacement for C's for-loop I recently wrote an entry on my blog regarding unit testing using prime numbers as an example.

When I wrote the entry, I wrote my code keeping in minding that proposal SE-0007 has been accepted for Swift 3.0.  That is, C-style for loops will no longer be available in Swift as of 3.0, so I want to completely discontinue using them.

That is to say, where I might have written something like this:


for(int divisor = 7; divisor * divisor &lt;= value; divisor += 30) {



I was instead stuck with some real ugliness in my prime loop.

func isPrime(value: Int) -&gt; Bool {
    if value &lt; 2 { return false }
    if value % 2 == 0 { return value == 2 }
    if value % 3 == 0 { return value == 3 }
    if value % 5 == 0 { return value == 5 }
    if value == 7 { return true }

    var divisor = 7
    while divisor * divisor &lt;= value {
        if value % divisor == 0 { return false }
        if value % (divisor + 4) == 0 { return false }
        if value % (divisor + 6) == 0 { return false }
        if value % (divisor + 10) == 0 { return false }
        if value % (divisor + 12) == 0 { return false }
        if value % (divisor + 16) == 0 { return false }
        if value % (divisor + 22) == 0 { return false }
        if value % (divisor + 24) == 0 { return false }
        divisor += 30
    }

    return true
}


I am satisfied that this code works as I want.  I am also satisfied that is runs extraordinarily fast.  

What I do not like about this is the very round-about way I have to achieve the same behavior a C-style for loop would have given me.  In particular, it is the termination point that concerns me.  I could easily get the same loop steps with the stride function:


for divisor in 7.stride(through: value, by: 30) {



But this doesn't allow for the same early stopping point:


divisor * divisior &lt;= value



And making the first line of the loop check this isn't much better:


for divisor in 7.stride(through: value, by: 30) {
    if divisor * divisor &gt; value { break }



And the biggest problem with the while loop which I'd like reviewed is that the divisor variable has a scope larger than I'd like, and the update statement doesn't come until the very end of the while loop (a problem that becomes more complex if your loop has any continue statements in it anywhere that allow iterations to break out early and jump to the next iteration).

So, in the end, I want a very, very fast isPrime() checker (it should be at least as fast as the above code), but I'd like the ugliness of my while loop to be significantly cleaned up.
Python also has no C-style for-loop.  A lot of Python novices write clumsy while-loops as a result.  However, once you learn the Pythonic idioms for looping, you'll wonder why other languages aren't more like Python.

The trick is to get to know…


the range() built-in function, which looks a lot like the stride(through: by:) that you suggested
the enumerate() built-in function, for when you need to iterate over a list and also increment a counter at the same time
the itertools library for more complex situations


If I had to translate your Swift code to Python, I would do it using itertools.count() to generate the infinite sequence [7, 37, 67, 97, …], and itertools.takewhile() to terminate it.

from itertools import count, takewhile

def is_prime(value):
    if value &lt; 2: return False
    if value % 2 == 0: return value == 2
    if value % 3 == 0: return value == 3
    if value % 5 == 0: return value == 5
    if value == 7: return True

    for divisor in takewhile(lambda d: d * d &lt;= value, count(7, 30)):
        if value % divisor == 0: return False
        for offset in [4, 6, 10, 12, 16, 22, 24]:
            if value % (divisor + offset) == 0: return False
    return True


Kevin Ballard has posted a proposal on the swift-evolution mailing list to introduce a takeWhile() to the standard library.  I think that a rich library for manipulating sequence types would make a good replacement for C-style for-loops.