Skip to content

Commit 7c2f25f

Browse files
committed
Add Stream.seq() for generating potentially infinite streams of values
1 parent dd6fb4a commit 7c2f25f

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

lib/elixir/lib/stream.ex

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ defmodule Stream do
9393
`Stream.cycle/1`.
9494
"""
9595

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

98103
defimpl Enumerable, for: Lazy do
@@ -262,6 +267,28 @@ defmodule Stream do
262267
end]
263268
end
264269

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+
291+
265292
@doc """
266293
Lazily takes the next `n` items from the enumerable and stops
267294
enumeration.

lib/elixir/test/elixir/stream_test.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ defmodule StreamTest do
6767
assert Enum.to_list(stream) == [1,3]
6868
end
6969

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+
7087
test :take do
7188
stream = Stream.take(1..1000, 5)
7289
assert is_lazy(stream)

0 commit comments

Comments
 (0)