- This is the 20th post in a multipart series.
If you want to read more, see our series index
Kotlin has two loops, while
and for
. When I started I was like, “yup, I know those…” - except I didn’t. while
works the way I expected it would but for
it is something else.
First Kotlin does not have a traditional for
loop, eg for (var i =0;i< max; i++)
… the for
loop in Kotlin is closer to the iterator foreach
loop in C#.
Basic
Let’s start with the basics, how do I run a loop, say 10 times where we print out 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
:
fun main(args:Array) {
for(i in 0..9) {
println(i)
}
}
In this, we use a ClosedRange (0..9) to state the start and end of the loop. This would be the same as for (var i=0; i< 10; i++)
.
Now, normally we want to loop over an array of items, so we can do this in two ways. First the equivalent of the C# for iterator/JS for of
:
fun main(args:Array
and if we do the older style of using a normal for
loop and using the index we have:
fun main(args:Array
What is awesome in the above is the Range, rather than having the inclusive lower and inclusive upper bounds of the ..
range we using the keyword until
which gives us an exclusive upper bound.
Kotlin is all about helpers, and last time we looked at destructuring so it shouldn’t be a surprise we can use that to have BOTH the index and the value in the for
loop.
fun main(args:Array
Extras
The for
loop has two additional options worth knowing; the first is downTo
which loops from largest to smallest. This example which print 4321
):
for (i in 4 downTo 1) print(i)
The second is step
which allows you to control how many steps to take when moving to the next item, for this example we will get 42
:
for (i in 4 downTo 1 step 2) print(i)
Operator
Adding support for this to our own classes is trivial, we merely need to add the interface Iterator<T>
to our class. This adds two methods, fun next():T
which should return the next value in the collection and fun hasNext():Boolean
which should return true if there is another value available. Let us look at doing this with a class of prime numbers but for our example, we will add one condition since there are infinite primes we will have a top bound so it eventually ends - this is stored in the maxToHunt
variable.
In the code our next
function not only returns the next value, it calculates the NEXT NEXT value too which lets us set if there are more primes left if next
is called again.
class PrimeNumbers : Iterator {
var currentPrime = 1;
val maxToHunt = 100;
var morePrimesToFind = true;
override fun next():Int {
val result = this.currentPrime;
this.currentPrime += 1;
while(this.currentPrime < this.maxToHunt) {
var primeFound = true
for(divisor in this.currentPrime-1 downTo 2) {
if (this.currentPrime % divisor == 0) {
this.currentPrime += 1
primeFound = false
break
}
}
if (primeFound) {
break
}
}
this.morePrimesToFind = this.currentPrime < this.maxToHunt
return result
}
override fun hasNext() = this.morePrimesToFind
}
fun main(args:Array) {
for (i in PrimeNumbers()) {
println(“$i is prime“)
}
}