Range Over Iterators in Nim

Our example demonstrates the use of the Range feature on iterators, showcasing a series of operations on a list, and generating Fibonacci numbers. Here’s how you can achieve similar functionality in Nim:

import lists, sequtils

type
  Element*[T] = ref object
    next: Element[T]
    val: T

  List*[T] = ref object
    head, tail: Element[T]

proc push*[T](lst: List[T], v: T) =
  let e = Element[T](val: v)
  if lst.tail == nil:
    lst.head = e
    lst.tail = e
  else:
    lst.tail.next = e
    lst.tail = e

proc all*[T](lst: List[T]): iterator(): T =
  iterator all: T =
    var e = lst.head
    while e != nil:
      yield e.val
      e = e.next

proc genFib*(): iterator(): int =
  iterator genFib: int =
    var a, b = 1, 1
    while true:
      yield a
      (a, b) = (b, a + b)

proc main() =
  let lst = List[int]()
  lst.push(10)
  lst.push(13)
  lst.push(23)

  for e in lst.all():
    echo e

  let all = toSeq(lst.all())
  echo "all:", all

  for n in genFib():
    if n >= 10:
      break
    echo n

main()

Let’s break down the example:

  1. We define two types: Element and List. Element contains a value and a reference to the next element, while List contains references to the head and tail of the list.

  2. The push procedure appends a new value to the end of the list. If the list is empty, it initializes both head and tail with the new element. If not, it adds the new element to the end and updates tail.

  3. The all procedure returns an iterator. This iterator traverses from the head to the tail, yielding each element’s value.

  4. The genFib procedure returns an iterator that generates Fibonacci numbers. It continues generating as long as the consumer keeps requesting more numbers by yielding.

  5. In the main procedure, we create a List, push some values into it, and then use the all iterator in a loop to print each value.

  6. We collect all values from the list’s iterator into a sequence using toSeq and print them.

  7. The genFib iterator is used in a loop to generate and print Fibonacci numbers until a number greater than or equal to 10 is encountered.

The translated code showcases idiomatic Nim constructs to mimic the original functionality. Nim’s iterators are similar to those in the original code’s language, allowing us to range over custom data structures and infinite sequences seamlessly.