This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Iterable for all natural numbers?

No replies
mtopol
Joined: 2009-01-12,
User offline. Last seen 42 years 45 weeks ago.

I often encounter the need for a non-strict, non-caching (non-lazy?) infinite
Iterable that simply contains all the natural numbers, or, more generally,
its Iterator computes the next element with some user-provided stateful
algorithm (internal state + a function on it). I still kind of expect to
have at least something like open-ended Ranges in the standard library. For
example, Range.from(Int), just like we have Stream.from(Int), but without
caching the computed elements. One specific use is indexing another infinite
sequence using zip. Is there such a thing in the Scala library after all?
Currently I use this code:

class InfiniteIterable[S, E](
init: S, calcNext: Array[S]=>E) extends Iterable.Projection[E]
{
override val hasDefiniteSize, isEmpty = false
def elements = new Iterator[E] {
val state: Array[S] = new Array[S](1); state(0) = init
val hasNext = true
def next = calcNext(state)
}
def apply(i:Int) = {
val elems = elements
for (j <- 1 until i) elems.next
elems.next
}
}

I can implement a sequence of naturals like this:

def naturals(start:Int) = new InfiniteIterable[Int, Int](start,
prevNat => {val curr = prevNat(0); prevNat(0) += 1; curr})

It is also quite simple to implement a Fibonacci sequence, for example:

val fibs = new InfiniteIterable[Queue[BigInt], BigInt](state, lastTwoArr =>
{
val lastTwo = lastTwoArr(0)
lastTwo enqueue (if (lastTwo.length < 2) 1 else lastTwo reduceLeft (_+_))
lastTwo.last
})

There are many inelegancies here (using Array as a mutable container of
state, for example), but it helps. I would like to know how to do this more
elegantly, leveraging the existing library to a greater extent. I can't help
but feel that I'm reinventing the wheel here, and a bumpy one, too.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland