Skip to content

Commit 6ef031b

Browse files
committed
Add Enum.concat/1,2 and Stream.concat/1,2
1 parent 5f1e5eb commit 6ef031b

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

lib/elixir/lib/enum.ex

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,57 @@ defmodule Enum do
221221
end
222222
end
223223

224+
@doc """
225+
Given a list of enumerables, concatenate the enumerables into a single list.
226+
227+
## Examples
228+
229+
iex> Enum.concat([1..3, 4..6, 7..9])
230+
[1,2,3,4,5,6,7,8,9]
231+
232+
iex> Enum.concat([[1, [2], 3], [4], [5, 6]])
233+
[1,[2],3,4,5,6]
234+
235+
"""
236+
@spec concat([t]) :: t
237+
def concat(enumerables) when is_list(enumerables) do
238+
do_concat(enumerables)
239+
end
240+
241+
@doc """
242+
Concatenates the enumerable on the right with the enumerable on the left.
243+
244+
This function produces the same result the `++` operator for lists.
245+
246+
## Examples
247+
248+
iex> Enum.concat(1..3, 4..6)
249+
[1,2,3,4,5,6]
250+
251+
iex> Enum.concat([1, 2, 3], [4, 5, 6])
252+
[1,2,3,4,5,6]
253+
254+
"""
255+
@spec concat(t, t) :: t
256+
def concat(left, right) when is_list(left) and is_list(right) do
257+
left ++ right
258+
end
259+
260+
def concat(left, right) do
261+
do_concat([left, right])
262+
end
263+
264+
defp do_concat(enumerables, acc // [])
265+
266+
defp do_concat([enumerable|enumerables], acc) do
267+
acc = Enumerable.reduce(enumerable, acc, &[&1|&2])
268+
do_concat(enumerables, acc)
269+
end
270+
271+
defp do_concat([], acc) do
272+
:lists.reverse(acc)
273+
end
274+
224275
@doc """
225276
Drops the first `count` items from `collection`.
226277
Expects an ordered collection.

lib/elixir/lib/stream.ex

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,45 @@ defmodule Stream do
131131
@type index :: non_neg_integer
132132
@type default :: any
133133

134+
@doc """
135+
Creates a stream that enumerates each enumerable in a list.
136+
137+
## Examples
138+
139+
iex> stream = Stream.concat([1..3, 4..6, 7..9])
140+
iex> Enum.to_list(stream)
141+
[1,2,3,4,5,6,7,8,9]
142+
143+
"""
144+
@spec concat([Enumerable.t]) :: t
145+
def concat(enumerables) do
146+
do_concat(enumerables, &1, &2)
147+
end
148+
149+
@doc """
150+
Creates a stream that enumerates the first argument, followed by the second.
151+
152+
## Examples
153+
154+
iex> stream = Stream.concat(1..3, 4..6)
155+
iex> Enum.to_list(stream)
156+
[1,2,3,4,5,6]
157+
158+
"""
159+
@spec concat(Enumerable.t, Enumerable.t) :: t
160+
def concat(first, second) do
161+
do_concat([first, second], &1, &2)
162+
end
163+
164+
defp do_concat([enumerable|enumerables], acc, fun) do
165+
acc = Enumerable.reduce(enumerable, acc, fun)
166+
do_concat(enumerables, acc, fun)
167+
end
168+
169+
defp do_concat([], acc, _fun) do
170+
acc
171+
end
172+
134173
@doc """
135174
Creates a stream that cycles through the given enumerable,
136175
infinitely.

0 commit comments

Comments
 (0)