Skip to content

Commit 8c3c0a9

Browse files
committed
Add Stream.iterate
1 parent 7c2f25f commit 8c3c0a9

File tree

2 files changed

+29
-44
lines changed

2 files changed

+29
-44
lines changed

lib/elixir/lib/stream.ex

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,10 @@ 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

96-
@compile {:inline, increment_func: 0}
97-
98-
@doc false
99-
def increment_func(), do: &1+1
100-
10196
defrecord Lazy, [:enumerable, :fun, :acc]
10297

10398
defimpl Enumerable, for: Lazy do
@@ -225,6 +220,27 @@ defmodule Stream do
225220
end]
226221
end
227222

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+
228244
@doc """
229245
Creates a stream that will apply the given function on
230246
enumeration.
@@ -267,27 +283,6 @@ defmodule Stream do
267283
end]
268284
end
269285

270-
@doc """
271-
Emit a sequence of values, starting with `start_value`. Successive
272-
values are generated by calling `incr_func` on the previous value.
273-
The default parameters generate a sequence of integers starting at 0.
274-
275-
## Examples
276-
277-
iex> Stream.seq |> Enum.take(5)
278-
[0,1,2,3,4]
279-
280-
"""
281-
282-
@spec seq((element -> element), element) :: Lazy.t
283-
def seq(incr_fun // &1+1, start_value // 0) do
284-
do_seq(incr_fun, start_value, &1, &2)
285-
end
286-
287-
defp do_seq(incr_fun, start_value, acc, fun) do
288-
do_seq(incr_fun, incr_fun.(start_value), fun.(start_value, acc), fun)
289-
end
290-
291286

292287
@doc """
293288
Lazily takes the next `n` items from the enumerable and stops

lib/elixir/test/elixir/stream_test.exs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ defmodule StreamTest do
5555
assert Enum.to_list(stream) == [2]
5656
end
5757

58+
test :iterate do
59+
stream = Stream.iterate(0, &1+2)
60+
assert Enum.take(stream, 5) == [0,2,4,6,8]
61+
stream = Stream.iterate(5, &1+2)
62+
assert Enum.take(stream, 5) == [5,7,9,11,13]
63+
end
64+
5865
test :map do
5966
stream = Stream.map([1,2,3], &1 * 2)
6067
assert is_lazy(stream)
@@ -67,23 +74,6 @@ defmodule StreamTest do
6774
assert Enum.to_list(stream) == [1,3]
6875
end
6976

70-
test :seq_default do
71-
stream = Stream.seq
72-
assert Enum.take(stream, 5) == [0,1,2,3,4]
73-
end
74-
75-
test :seq_with_explicit_but_default do
76-
stream = Stream.seq(&1+1, 0)
77-
assert Enum.take(stream, 5) == [0,1,2,3,4]
78-
end
79-
80-
test :seq_for_every_second_number do
81-
stream = Stream.seq(&1+2)
82-
assert Enum.take(stream, 5) == [0,2,4,6,8]
83-
stream = Stream.seq(&1+2, 5)
84-
assert Enum.take(stream, 5) == [5,7,9,11,13]
85-
end
86-
8777
test :take do
8878
stream = Stream.take(1..1000, 5)
8979
assert is_lazy(stream)

0 commit comments

Comments
 (0)