Skip to content

Instantly share code, notes, and snippets.

@aloiscochard
Created November 2, 2011 16:06
Show Gist options
  • Save aloiscochard/1334040 to your computer and use it in GitHub Desktop.
Save aloiscochard/1334040 to your computer and use it in GitHub Desktop.
Scala [In]finite Stream Constructor
import Stream._
/** A possibly finite stream that repeatedly applies a given function to a start value.
*
* @param start the start value of the stream
* @param f the function that's repeatedly applied
* @return the stream returning the possibly finite sequence of values `start, f(start), f(f(start)), ...`
*/
def iterate[A](f: A => A, a: A): Stream[A] = unfold((x: A) => Some((x, f(x))), a)
def unfold[A, B](start: B)(f: B => Option[Tuple2[A,B]]): Stream[A] = f(start) match {
case Some((elem, next)) => elem #:: unfold(next)(f)
case None => empty
}
// Could be integrated here -> https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/collection/immutable/Stream.scala#L647
@cvogt
Copy link

cvogt commented Feb 23, 2015

@aloiscochard For what use case is unfold better than iterate?
@missingfaktor's example seems clearer using iterate rather than unfold
Stream.iterate(5)(+1).map(*2).takeWhile(x < 200)

@copumpkin
Copy link

@cvogt for anything where it doesn't make sense to keep asking for stuff indefinitely. In your example, +1 doesn't care if you keep running it forever, so you're safe with an intermediate infinite stream, but in many more realistic use cases, you have a process that you're going to have to repeat until some condition stops being true, and then you need to stop, and that's based on a piece of internal state that is no longer accessible by the time you use takeWhile. A simple example of a good use case here is a pagination API that hands you a "marker" telling you how to ask for more. You can't just keep asking for more forever and filter later.

Also, unfold is in some senses the most fundamental operation on a Stream, much like how fold (right) is a fundamental operation on List.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment