Range Over Iterators in Scala

Our first program will demonstrate how to use iterators. Here’s the full source code.

object IteratorExample {
  def main(args: Array[String]): Unit = {
    val lst = new List[Int]()
    lst.push(10)
    lst.push(13)
    lst.push(23)

    // Using the iterator with a for-comprehension
    for (e <- lst.all) {
      println(e)
    }

    // Collect all elements to a vector
    val all = lst.all.toVector
    println(s"all: $all")

    // Generate Fibonacci numbers
    for (n <- genFib if n < 10) {
      println(n)
    }
  }

  class List[T] {
    private class Element(val value: T, var next: Element)

    private var head: Element = _
    private var tail: Element = _

    def push(value: T): Unit = {
      val newElem = new Element(value, null)
      if (tail == null) {
        head = newElem
        tail = newElem
      } else {
        tail.next = newElem
        tail = newElem
      }
    }

    def all: Iterator[T] = new Iterator[T] {
      private var current = head

      override def hasNext: Boolean = current != null

      override def next(): T = {
        val value = current.value
        current = current.next
        value
      }
    }
  }

  def genFib: Iterator[Int] = new Iterator[Int] {
    private var (a, b) = (1, 1)

    override def hasNext: Boolean = true

    override def next(): Int = {
      val value = a
      a = b
      b = value + b
      value
    }
  }
}

Let’s break down what’s happening in this code:

  1. List Class:

    • We define a generic List class with a nested Element class representing each node in the linked list.
    • The push method adds elements to the end of the list.
    • The all method returns an iterator for the list.
  2. Iterator for List:

    • The all method creates a new iterator that traverses the list starting from the head, yielding each element’s value until the end.
  3. Generating Fibonacci Numbers:

    • The genFib method creates an iterator for Fibonacci numbers. It keeps generating values as long as needed.
  4. Main Method:

    • We create a list and add some integers.
    • We use a for loop with the list’s iterator to print each element.
    • We collect all elements into a vector and print them.
    • We use another iterator to generate Fibonacci numbers and print them until we encounter a number greater than or equal to 10.

To run the program, compile and execute it using the following commands:

$ scalac IteratorExample.scala
$ scala IteratorExample

This will output:

10
13
23
all: Vector(10, 13, 23)
1
1
2
3
5
8

Now that we can create and use iterators in Scala, let’s learn more about the language’s capabilities.