Skip to content

Commit cc3634e

Browse files
author
José Valim
committed
Merge pull request #1390 from pragdave/iterate
Iterate
2 parents 5a5ab18 + a2c6630 commit cc3634e

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

lib/elixir/lib/stream.ex

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ defmodule Stream do
8989
to `Stream.map/2`, we have automatically created a stream that will
9090
multiply the items in the list by 2 on enumeration.
9191
92-
This module also provides other functions for creating streams, like
92+
This module also provides other functions for creating streams, such as
9393
`Stream.cycle/1`.
9494
"""
9595

@@ -220,6 +220,27 @@ defmodule Stream do
220220
end]
221221
end
222222

223+
@doc """
224+
Emit a sequence of values, starting with `start_value`. Successive
225+
values are generated by calling `next_fun` on the previous value.
226+
227+
228+
## Examples
229+
230+
iex> Stream.iterate(0, &1+1) |> Enum.take(5)
231+
[0,1,2,3,4]
232+
233+
"""
234+
235+
@spec iterate(element, (element -> element)) :: Lazy.t
236+
def iterate(start_value, next_fun) do
237+
do_iterate(start_value, next_fun, &1, &2)
238+
end
239+
240+
defp do_iterate(start_value, next_fun, acc, fun) do
241+
do_iterate(next_fun.(start_value), next_fun, fun.(start_value, acc), fun)
242+
end
243+
223244
@doc """
224245
Creates a stream that will apply the given function on
225246
enumeration.
@@ -262,6 +283,27 @@ defmodule Stream do
262283
end]
263284
end
264285

286+
287+
@doc """
288+
Returns a stream generated by calling `generator_fun` repeatedly.
289+
290+
## Examples
291+
292+
iex> Stream.repeatedly(function(:random.uniform/0)) |> Enum.take(3)
293+
[0.4435846174457203, 0.7230402056221108, 0.94581636451987]
294+
295+
"""
296+
@spec repeatedly(( -> element)) :: Lazy.t
297+
def repeatedly(generator_fun)
298+
when is_function(generator_fun, 0) do
299+
do_repeatedly(generator_fun, &1, &2)
300+
end
301+
302+
defp do_repeatedly(generator_fun, acc, fun) do
303+
do_repeatedly(generator_fun, fun.(generator_fun.(), acc), fun)
304+
end
305+
306+
265307
@doc """
266308
Lazily takes the next `n` items from the enumerable and stops
267309
enumeration.

lib/elixir/test/elixir/stream_test.exs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ defmodule StreamTest do
5757
assert Enum.to_list(stream) == [2]
5858
end
5959

60+
test :iterate do
61+
stream = Stream.iterate(0, &1+2)
62+
assert Enum.take(stream, 5) == [0,2,4,6,8]
63+
stream = Stream.iterate(5, &1+2)
64+
assert Enum.take(stream, 5) == [5,7,9,11,13]
65+
end
66+
6067
test :map do
6168
stream = Stream.map([1,2,3], &1 * 2)
6269
assert is_lazy(stream)
@@ -69,6 +76,14 @@ defmodule StreamTest do
6976
assert Enum.to_list(stream) == [1,3]
7077
end
7178

79+
test :repeatedly do
80+
stream = Stream.repeatedly(fn -> 1 end)
81+
assert Enum.take(stream, 5) == [1,1,1,1,1]
82+
stream = Stream.repeatedly(function(:random.uniform/0))
83+
[r1,r2] = Enum.take(stream, 2)
84+
assert r1 != r2
85+
end
86+
7287
test :take do
7388
stream = Stream.take(1..1000, 5)
7489
assert is_lazy(stream)

0 commit comments

Comments
 (0)