elixir-lang/elixir — pull request #1713 by kachayev (2013-09-14 16:38:04+00:00)
Title: Stream.unfold implementation

Folding and unfolding operations are basics for Stream processing. Fold is represented in Elixir as `reduce`. As for unfold, we have only `Stream.iterate` which is definitely only the simple partial case of generic unfold. More about unfolds as duality for folds: [Anamorphism](http://en.wikipedia.org/wiki/Anamorphism).

PR provides implementation and tests for `Stream.unfold` function. The idea is to "generate" stream using generator function and "seed" value. Generator function takes element and return tuple of two values: first one is to be emitted to resulting stream, second one is to be used for next generator function call.

To emulate `Stream.iterate` function using `Stream.unfold` you can just wrap `next_fun` to return tuple of two same elements:

```elixir
iex> Stream.unfold(0, &({&1, &1+1})) |> Enum.take(5)
[0,1,2,3,4]
```

But there are much more powerful usage examples. I.e. generating fibonacci sequence:

```elixir
iex> Stream.unfold({0, 1}, fn {f, s} -> {s, {s, f+s}} end) |> Enum.take(10)
[1,1,2,3,5,8,13,21,34,55]
```

I also reimplement `Stream.iterate` function in order to reduce code duplication. It was not so easy to do, cause classical implementation of `iterate` is just

```elixir
def iterate(start, f) do
unfold(start, &({&1, f.(&1)})
end
```

but in Elixir it should works in other way, regarding to next comment in unit test for `Stream.iterate`: **Only calculate values if needed**. That's why I used `Stream.concat` to build resulting stream from two parts: list with starting value and unfolded by generator function.