Skip to content

Commit 6886f7c

Browse files
committed
Address bootstrap
1 parent 4a3f61f commit 6886f7c

File tree

3 files changed

+140
-136
lines changed

3 files changed

+140
-136
lines changed

lib/elixir/lib/enum.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -4136,7 +4136,7 @@ defmodule Enum do
41364136

41374137
def zip_reduce(left, right, acc, reducer) when is_function(reducer, 3) do
41384138
reduce = fn [l, r], acc -> {:cont, reducer.(l, r, acc)} end
4139-
Stream.zip_with([left, right], & &1).({:cont, acc}, reduce) |> elem(1)
4139+
R.zip_with([left, right], & &1).({:cont, acc}, reduce) |> elem(1)
41404140
end
41414141

41424142
@doc """
@@ -4171,7 +4171,7 @@ defmodule Enum do
41714171
def zip_reduce([], acc, reducer) when is_function(reducer, 2), do: acc
41724172

41734173
def zip_reduce(enums, acc, reducer) when is_function(reducer, 2) do
4174-
Stream.zip_with(enums, & &1).({:cont, acc}, &{:cont, reducer.(&1, &2)}) |> elem(1)
4174+
R.zip_with(enums, & &1).({:cont, acc}, &{:cont, reducer.(&1, &2)}) |> elem(1)
41754175
end
41764176

41774177
## Helpers

lib/elixir/lib/stream.ex

+2-134
Original file line numberDiff line numberDiff line change
@@ -1371,140 +1371,8 @@ defmodule Stream do
13711371
@doc since: "1.12.0"
13721372
@spec zip_with(enumerables, (Enumerable.t() -> term)) :: Enumerable.t()
13731373
when enumerables: [Enumerable.t()] | Enumerable.t()
1374-
def zip_with(enumerables, zip_fun) when is_function(zip_fun, 1) do
1375-
if is_list(enumerables) and :lists.all(&is_list/1, enumerables) do
1376-
&zip_list(enumerables, &1, &2, zip_fun)
1377-
else
1378-
&zip_enum(enumerables, &1, &2, zip_fun)
1379-
end
1380-
end
1381-
1382-
defp zip_list(_enumerables, {:halt, acc}, _fun, _zip_fun) do
1383-
{:halted, acc}
1384-
end
1385-
1386-
defp zip_list(enumerables, {:suspend, acc}, fun, zip_fun) do
1387-
{:suspended, acc, &zip_list(enumerables, &1, fun, zip_fun)}
1388-
end
1389-
1390-
defp zip_list([], {:cont, acc}, _fun, _zip_fun), do: {:done, acc}
1391-
1392-
defp zip_list(enumerables, {:cont, acc}, fun, zip_fun) do
1393-
case zip_list_heads_tails(enumerables, [], []) do
1394-
{heads, tails} -> zip_list(tails, fun.(zip_fun.(heads), acc), fun, zip_fun)
1395-
:error -> {:done, acc}
1396-
end
1397-
end
1398-
1399-
defp zip_list_heads_tails([[head | tail] | rest], heads, tails) do
1400-
zip_list_heads_tails(rest, [head | heads], [tail | tails])
1401-
end
1402-
1403-
defp zip_list_heads_tails([[] | _rest], _heads, _tails) do
1404-
:error
1405-
end
1406-
1407-
defp zip_list_heads_tails([], heads, tails) do
1408-
{:lists.reverse(heads), :lists.reverse(tails)}
1409-
end
1410-
1411-
defp zip_enum(enumerables, acc, fun, zip_fun) do
1412-
step = fn x, acc ->
1413-
{:suspend, :lists.reverse([x | acc])}
1414-
end
1415-
1416-
enum_funs =
1417-
Enum.map(enumerables, fn enum ->
1418-
{&Enumerable.reduce(enum, &1, step), [], :cont}
1419-
end)
1420-
1421-
do_zip_enum(enum_funs, acc, fun, zip_fun)
1422-
end
1423-
1424-
# This implementation of do_zip_enum/4 works for any number of streams to zip
1425-
defp do_zip_enum(zips, {:halt, acc}, _fun, _zip_fun) do
1426-
do_zip_close(zips)
1427-
{:halted, acc}
1428-
end
1429-
1430-
defp do_zip_enum(zips, {:suspend, acc}, fun, zip_fun) do
1431-
{:suspended, acc, &do_zip_enum(zips, &1, fun, zip_fun)}
1432-
end
1433-
1434-
defp do_zip_enum([], {:cont, acc}, _callback, _zip_fun) do
1435-
{:done, acc}
1436-
end
1437-
1438-
defp do_zip_enum(zips, {:cont, acc}, callback, zip_fun) do
1439-
try do
1440-
do_zip_next(zips, acc, callback, [], [], zip_fun)
1441-
catch
1442-
kind, reason ->
1443-
do_zip_close(zips)
1444-
:erlang.raise(kind, reason, __STACKTRACE__)
1445-
else
1446-
{:next, buffer, acc} ->
1447-
do_zip_enum(buffer, acc, callback, zip_fun)
1448-
1449-
{:done, _acc} = other ->
1450-
other
1451-
end
1452-
end
1453-
1454-
# do_zip_next/6 computes the next tuple formed by
1455-
# the next element of each zipped stream.
1456-
defp do_zip_next(
1457-
[{_, [], :halt} | zips],
1458-
acc,
1459-
_callback,
1460-
_yielded_elems,
1461-
buffer,
1462-
_zip_fun
1463-
) do
1464-
do_zip_close(:lists.reverse(buffer, zips))
1465-
{:done, acc}
1466-
end
1467-
1468-
defp do_zip_next([{fun, [], :cont} | zips], acc, callback, yielded_elems, buffer, zip_fun) do
1469-
case fun.({:cont, []}) do
1470-
{:suspended, [elem | next_acc], fun} ->
1471-
next_buffer = [{fun, next_acc, :cont} | buffer]
1472-
do_zip_next(zips, acc, callback, [elem | yielded_elems], next_buffer, zip_fun)
1473-
1474-
{_, [elem | next_acc]} ->
1475-
next_buffer = [{fun, next_acc, :halt} | buffer]
1476-
do_zip_next(zips, acc, callback, [elem | yielded_elems], next_buffer, zip_fun)
1477-
1478-
{_, []} ->
1479-
# The current zipped stream terminated, so we close all the streams
1480-
# and return {:halted, acc} (which is returned as is by do_zip/3).
1481-
do_zip_close(:lists.reverse(buffer, zips))
1482-
{:done, acc}
1483-
end
1484-
end
1485-
1486-
defp do_zip_next(
1487-
[{fun, zip_acc, zip_op} | zips],
1488-
acc,
1489-
callback,
1490-
yielded_elems,
1491-
buffer,
1492-
zip_fun
1493-
) do
1494-
[elem | rest] = zip_acc
1495-
next_buffer = [{fun, rest, zip_op} | buffer]
1496-
do_zip_next(zips, acc, callback, [elem | yielded_elems], next_buffer, zip_fun)
1497-
end
1498-
1499-
defp do_zip_next([] = _zips, acc, callback, yielded_elems, buffer, zip_fun) do
1500-
# "yielded_elems" is a reversed list of results for the current iteration of
1501-
# zipping. That is to say, the nth element from each of the enums being zipped.
1502-
# It needs to be reversed and passed to the zipping function so it can do it's thing.
1503-
{:next, :lists.reverse(buffer), callback.(zip_fun.(:lists.reverse(yielded_elems)), acc)}
1504-
end
1505-
1506-
defp do_zip_close(zips) do
1507-
:lists.foreach(fn {fun, _, _} -> fun.({:halt, []}) end, zips)
1374+
def zip_with(enumerables, zip_fun) do
1375+
R.zip_with(enumerables, zip_fun)
15081376
end
15091377

15101378
## Sources

lib/elixir/lib/stream/reducers.ex

+136
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,142 @@ defmodule Stream.Reducers do
22
# Collection of reducers and utilities shared by Enum and Stream.
33
@moduledoc false
44

5+
def zip_with(enumerables, zip_fun) when is_function(zip_fun, 1) do
6+
if is_list(enumerables) and :lists.all(&is_list/1, enumerables) do
7+
&zip_list(enumerables, &1, &2, zip_fun)
8+
else
9+
&zip_enum(enumerables, &1, &2, zip_fun)
10+
end
11+
end
12+
13+
defp zip_list(_enumerables, {:halt, acc}, _fun, _zip_fun) do
14+
{:halted, acc}
15+
end
16+
17+
defp zip_list(enumerables, {:suspend, acc}, fun, zip_fun) do
18+
{:suspended, acc, &zip_list(enumerables, &1, fun, zip_fun)}
19+
end
20+
21+
defp zip_list([], {:cont, acc}, _fun, _zip_fun), do: {:done, acc}
22+
23+
defp zip_list(enumerables, {:cont, acc}, fun, zip_fun) do
24+
case zip_list_heads_tails(enumerables, [], []) do
25+
{heads, tails} -> zip_list(tails, fun.(zip_fun.(heads), acc), fun, zip_fun)
26+
:error -> {:done, acc}
27+
end
28+
end
29+
30+
defp zip_list_heads_tails([[head | tail] | rest], heads, tails) do
31+
zip_list_heads_tails(rest, [head | heads], [tail | tails])
32+
end
33+
34+
defp zip_list_heads_tails([[] | _rest], _heads, _tails) do
35+
:error
36+
end
37+
38+
defp zip_list_heads_tails([], heads, tails) do
39+
{:lists.reverse(heads), :lists.reverse(tails)}
40+
end
41+
42+
defp zip_enum(enumerables, acc, fun, zip_fun) do
43+
step = fn x, acc ->
44+
{:suspend, :lists.reverse([x | acc])}
45+
end
46+
47+
enum_funs =
48+
Enum.map(enumerables, fn enum ->
49+
{&Enumerable.reduce(enum, &1, step), [], :cont}
50+
end)
51+
52+
do_zip_enum(enum_funs, acc, fun, zip_fun)
53+
end
54+
55+
# This implementation of do_zip_enum/4 works for any number of streams to zip
56+
defp do_zip_enum(zips, {:halt, acc}, _fun, _zip_fun) do
57+
do_zip_close(zips)
58+
{:halted, acc}
59+
end
60+
61+
defp do_zip_enum(zips, {:suspend, acc}, fun, zip_fun) do
62+
{:suspended, acc, &do_zip_enum(zips, &1, fun, zip_fun)}
63+
end
64+
65+
defp do_zip_enum([], {:cont, acc}, _callback, _zip_fun) do
66+
{:done, acc}
67+
end
68+
69+
defp do_zip_enum(zips, {:cont, acc}, callback, zip_fun) do
70+
try do
71+
do_zip_next(zips, acc, callback, [], [], zip_fun)
72+
catch
73+
kind, reason ->
74+
do_zip_close(zips)
75+
:erlang.raise(kind, reason, __STACKTRACE__)
76+
else
77+
{:next, buffer, acc} ->
78+
do_zip_enum(buffer, acc, callback, zip_fun)
79+
80+
{:done, _acc} = other ->
81+
other
82+
end
83+
end
84+
85+
# do_zip_next/6 computes the next tuple formed by
86+
# the next element of each zipped stream.
87+
defp do_zip_next(
88+
[{_, [], :halt} | zips],
89+
acc,
90+
_callback,
91+
_yielded_elems,
92+
buffer,
93+
_zip_fun
94+
) do
95+
do_zip_close(:lists.reverse(buffer, zips))
96+
{:done, acc}
97+
end
98+
99+
defp do_zip_next([{fun, [], :cont} | zips], acc, callback, yielded_elems, buffer, zip_fun) do
100+
case fun.({:cont, []}) do
101+
{:suspended, [elem | next_acc], fun} ->
102+
next_buffer = [{fun, next_acc, :cont} | buffer]
103+
do_zip_next(zips, acc, callback, [elem | yielded_elems], next_buffer, zip_fun)
104+
105+
{_, [elem | next_acc]} ->
106+
next_buffer = [{fun, next_acc, :halt} | buffer]
107+
do_zip_next(zips, acc, callback, [elem | yielded_elems], next_buffer, zip_fun)
108+
109+
{_, []} ->
110+
# The current zipped stream terminated, so we close all the streams
111+
# and return {:halted, acc} (which is returned as is by do_zip/3).
112+
do_zip_close(:lists.reverse(buffer, zips))
113+
{:done, acc}
114+
end
115+
end
116+
117+
defp do_zip_next(
118+
[{fun, zip_acc, zip_op} | zips],
119+
acc,
120+
callback,
121+
yielded_elems,
122+
buffer,
123+
zip_fun
124+
) do
125+
[elem | rest] = zip_acc
126+
next_buffer = [{fun, rest, zip_op} | buffer]
127+
do_zip_next(zips, acc, callback, [elem | yielded_elems], next_buffer, zip_fun)
128+
end
129+
130+
defp do_zip_next([] = _zips, acc, callback, yielded_elems, buffer, zip_fun) do
131+
# "yielded_elems" is a reversed list of results for the current iteration of
132+
# zipping. That is to say, the nth element from each of the enums being zipped.
133+
# It needs to be reversed and passed to the zipping function so it can do it's thing.
134+
{:next, :lists.reverse(buffer), callback.(zip_fun.(:lists.reverse(yielded_elems)), acc)}
135+
end
136+
137+
defp do_zip_close(zips) do
138+
:lists.foreach(fn {fun, _, _} -> fun.({:halt, []}) end, zips)
139+
end
140+
5141
def chunk_every(chunk_by, enumerable, count, step, leftover) do
6142
limit = :erlang.max(count, step)
7143

0 commit comments

Comments
 (0)