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:
We define two types:
ElementandList.Elementcontains a value and a reference to the next element, whileListcontains references to the head and tail of the list.The
pushprocedure appends a new value to the end of the list. If the list is empty, it initializes bothheadandtailwith the new element. If not, it adds the new element to the end and updatestail.The
allprocedure returns an iterator. This iterator traverses from the head to the tail, yielding each element’s value.The
genFibprocedure returns an iterator that generates Fibonacci numbers. It continues generating as long as the consumer keeps requesting more numbers by yielding.In the
mainprocedure, we create aList, push some values into it, and then use thealliterator in a loop to print each value.We collect all values from the list’s iterator into a sequence using
toSeqand print them.The
genFibiterator 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.