Skip to content

Commit a1ec5f1

Browse files
committed
Clean up and fixes in reducer code
1 parent 45485fb commit a1ec5f1

File tree

3 files changed

+83
-169
lines changed

3 files changed

+83
-169
lines changed

lib/elixir/lib/enum.ex

Lines changed: 65 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ defmodule Enum do
8686
Counts for how many items the function returns true.
8787
"""
8888
@spec count(t, (element -> as_boolean(term))) :: non_neg_integer
89-
def count(collection, fun) when is_list(collection) do
90-
folder = fn(x, acc) -> if fun.(x), do: acc+1, else: acc end
91-
:lists.foldl(folder, 0, collection)
92-
end
93-
9489
def count(collection, fun) do
9590
I.reduce(collection, 0, fn(entry, acc) ->
9691
if fun.(entry), do: acc + 1, else: acc
@@ -129,10 +124,9 @@ defmodule Enum do
129124
end
130125

131126
def all?(collection, fun) do
132-
I.reduce(collection, nil, fn(entry, _) ->
133-
if fun.(entry), do: nil, else: throw(:enum_all?)
127+
I.reduce(collection, true, fn(entry, _) ->
128+
if fun.(entry), do: true, else: throw(:enum_all?)
134129
end)
135-
true
136130
catch
137131
:enum_all? -> false
138132
end
@@ -168,10 +162,9 @@ defmodule Enum do
168162
end
169163

170164
def any?(collection, fun) do
171-
I.reduce(collection, nil, fn(entry, _) ->
172-
if fun.(entry), do: throw(:enum_any?), else: nil
165+
I.reduce(collection, false, fn(entry, _) ->
166+
if fun.(entry), do: throw(:enum_any?), else: false
173167
end)
174-
false
175168
catch
176169
:enum_any? -> true
177170
end
@@ -224,12 +217,9 @@ defmodule Enum do
224217
end
225218

226219
def drop(collection, count) when count >= 0 do
227-
{ list, _ } = I.reduce(collection, { [], count }, fn(entry, { list, count }) ->
228-
if count > 0 do
229-
{ [], count - 1}
230-
else
231-
{ [entry|list], count }
232-
end
220+
{ list, _ } = I.reduce(collection, { [], count }, fn
221+
_, { _, count } when count > 0 -> { [], count - 1 }
222+
entry, { list, count } -> { [entry|list], count }
233223
end)
234224
:lists.reverse(list)
235225
end
@@ -254,8 +244,9 @@ defmodule Enum do
254244
end
255245

256246
def drop_while(collection, fun) do
257-
I.reduce(collection, [], fn(entry, acc) ->
258-
if fun.(entry), do: [], else: [entry|acc]
247+
I.reduce(collection, [], fn
248+
entry, [] -> if fun.(entry), do: [], else: [entry]
249+
entry, acc -> [entry|acc]
259250
end) |> :lists.reverse
260251
end
261252

@@ -314,8 +305,7 @@ defmodule Enum do
314305
end
315306

316307
def empty?(collection) do
317-
I.reduce(collection, nil, fn(_, _) -> throw(:enum_empty?) end)
318-
true
308+
I.reduce(collection, true, fn(_, _) -> throw(:enum_empty?) end)
319309
catch
320310
:enum_empty? -> false
321311
end
@@ -451,10 +441,9 @@ defmodule Enum do
451441
end
452442

453443
def find(collection, ifnone, fun) do
454-
I.reduce(collection, nil, fn(entry, _) ->
444+
I.reduce(collection, ifnone, fn(entry, _) ->
455445
if fun.(entry), do: throw({ :enum_find, entry })
456446
end)
457-
ifnone
458447
catch
459448
{ :enum_find, entry } -> entry
460449
end
@@ -482,11 +471,10 @@ defmodule Enum do
482471
end
483472

484473
def find_value(collection, ifnone, fun) do
485-
I.reduce(collection, nil, fn(entry, _) ->
474+
I.reduce(collection, ifnone, fn(entry, _) ->
486475
fun_entry = fun.(entry)
487476
if fun_entry, do: throw({ :enum_find, fun_entry })
488477
end)
489-
ifnone
490478
catch
491479
{ :enum_find, entry } -> entry
492480
end
@@ -571,13 +559,9 @@ defmodule Enum do
571559
:unicode.characters_to_list join(collection, :unicode.characters_to_binary(joiner))
572560
end
573561

574-
def join(collection, joiner) when is_list(collection) and is_binary(joiner) do
575-
do_join(collection, joiner, nil)
576-
end
577-
578562
def join(collection, joiner) when is_binary(joiner) do
579-
I.reduce(collection, nil, fn
580-
entry, nil -> to_binary(entry)
563+
I.reduce(collection, "", fn
564+
entry, "" -> to_binary(entry)
581565
entry, acc -> acc <> joiner <> to_binary(entry)
582566
end)
583567
end
@@ -642,16 +626,12 @@ defmodule Enum do
642626
def map_join(collection, joiner // "", mapper)
643627

644628
def map_join(collection, joiner, mapper) when is_list(joiner) do
645-
binary_to_list map_join(collection, list_to_binary(joiner), mapper)
646-
end
647-
648-
def map_join(collection, joiner, mapper) when is_list(collection) and is_binary(joiner) do
649-
do_map_join(collection, mapper, joiner, nil)
629+
:unicode.characters_to_list map_join(collection, :unicode.characters_to_binary(joiner), mapper)
650630
end
651631

652632
def map_join(collection, joiner, mapper) when is_binary(joiner) do
653-
I.reduce(collection, nil, fn
654-
entry, nil -> to_binary(mapper.(entry))
633+
I.reduce(collection, "", fn
634+
entry, "" -> to_binary(mapper.(entry))
655635
entry, acc -> acc <> joiner <> to_binary(mapper.(entry))
656636
end)
657637
end
@@ -672,10 +652,6 @@ defmodule Enum do
672652
673653
"""
674654
@spec map_reduce(t, any, (element, any -> any)) :: any
675-
def map_reduce(collection, acc, f) when is_list(collection) do
676-
:lists.mapfoldl(f, acc, collection)
677-
end
678-
679655
def map_reduce(collection, acc, fun) do
680656
{ list, acc } = I.reduce(collection, { [], acc }, fn(entry, { list, acc }) ->
681657
{ new_entry, acc } = fun.(entry, acc)
@@ -696,10 +672,6 @@ defmodule Enum do
696672
697673
"""
698674
@spec partition(t, (element -> any)) :: {list, list}
699-
def partition(collection, fun) when is_list(collection) do
700-
do_partition(collection, fun, [], [])
701-
end
702-
703675
def partition(collection, fun) do
704676
{ acc1, acc2 } = I.reduce(collection, { [], [] }, fn(entry, { acc1, acc2 }) ->
705677
if fun.(entry) do
@@ -724,10 +696,6 @@ defmodule Enum do
724696
725697
"""
726698
@spec reduce(t, any, (element, any -> any)) :: any
727-
def reduce(collection, acc, fun) when is_list(collection) do
728-
:lists.foldl(fun, acc, collection)
729-
end
730-
731699
def reduce(collection, acc, fun) do
732700
I.reduce(collection, acc, fun)
733701
end
@@ -852,17 +820,12 @@ defmodule Enum do
852820
end
853821

854822
def split_while(collection, fun) do
855-
{ _, list1, list2 } =
856-
I.reduce(collection, { false, [], [] }, fn(entry, { split, acc1, acc2 }) ->
857-
cond do
858-
split ->
859-
{ true, acc1, [entry|acc2] }
860-
fun.(entry) ->
861-
{ false, [entry|acc1], acc2 }
862-
true ->
863-
{ true, acc1, [entry|acc2] }
864-
end
865-
end)
823+
{ list1, list2 } = I.reduce(collection, { [], [] }, fn
824+
entry, { acc1, [] } ->
825+
if fun.(entry), do: { [entry|acc1], [] }, else: { acc1, [entry] }
826+
entry, { acc1, acc2 } ->
827+
{ acc1, [entry|acc2] }
828+
end)
866829

867830
{ :lists.reverse(list1), :lists.reverse(list2) }
868831
end
@@ -1024,9 +987,14 @@ defmodule Enum do
1024987
1025988
"""
1026989
@spec max(t) :: element | no_return
1027-
def max(collection) when is_list(collection) do
1028-
if collection == [], do: raise Enum.EmptyError
1029-
:lists.max(collection)
990+
def max([h|t]) do
991+
I.reduce(t, h, fn(entry, max) ->
992+
if entry > max, do: entry, else: max
993+
end)
994+
end
995+
996+
def max([]) do
997+
raise Enum.EmptyError
1030998
end
1031999

10321000
def max(collection) do
@@ -1038,7 +1006,7 @@ defmodule Enum do
10381006
end)
10391007

10401008
case result do
1041-
:first -> raise Enum.EmptyError
1009+
:first -> raise Enum.EmptyError
10421010
{ :reduce, max } -> max
10431011
end
10441012
end
@@ -1055,8 +1023,17 @@ defmodule Enum do
10551023
10561024
"""
10571025
@spec max(t, (element -> any)) :: element | no_return
1058-
def max(collection, fun) when is_list(collection) do
1059-
do_max_first(collection, fun)
1026+
def max([h|t], fun) do
1027+
{ max, _ } = I.reduce(t, { h, fun.(h) }, fn(entry, { _, fun_max } = old) ->
1028+
fun_entry = fun.(entry)
1029+
if fun_entry > fun_max, do: { entry, fun_entry }, else: old
1030+
end)
1031+
1032+
max
1033+
end
1034+
1035+
def max([], _fun) do
1036+
raise Enum.EmptyError
10601037
end
10611038

10621039
def max(collection, fun) do
@@ -1085,6 +1062,16 @@ defmodule Enum do
10851062
10861063
"""
10871064
@spec min(t) :: element | no_return
1065+
def min([h|t]) do
1066+
I.reduce(t, h, fn(entry, min) ->
1067+
if entry < min, do: entry, else: min
1068+
end)
1069+
end
1070+
1071+
def min([]) do
1072+
raise Enum.EmptyError
1073+
end
1074+
10881075
def min(collection) when is_list(collection) do
10891076
if collection == [], do: raise Enum.EmptyError
10901077
:lists.min(collection)
@@ -1115,8 +1102,17 @@ defmodule Enum do
11151102
11161103
"""
11171104
@spec min(t, (element -> any)) :: element | no_return
1118-
def min(collection, fun) when is_list(collection) do
1119-
do_min_first(collection, fun)
1105+
def min([h|t], fun) do
1106+
{ min, _ } = I.reduce(t, { h, fun.(h) }, fn(entry, { _, fun_min } = old) ->
1107+
fun_entry = fun.(entry)
1108+
if fun_entry < fun_min, do: { entry, fun_entry }, else: old
1109+
end)
1110+
1111+
min
1112+
end
1113+
1114+
def min([], _fun) do
1115+
raise Enum.EmptyError
11201116
end
11211117

11221118
def min(collection, fun) do
@@ -1252,50 +1248,6 @@ defmodule Enum do
12521248
ifnone
12531249
end
12541250

1255-
## join
1256-
1257-
defp do_join([h|t], joiner, nil) do
1258-
do_join(t, joiner, to_binary(h))
1259-
end
1260-
1261-
defp do_join([h|t], joiner, acc) do
1262-
acc = acc <> joiner <> to_binary(h)
1263-
do_join(t, joiner, acc)
1264-
end
1265-
1266-
defp do_join([], _joiner, acc) do
1267-
acc || ""
1268-
end
1269-
1270-
## map join
1271-
1272-
defp do_map_join([h|t], mapper, joiner, nil) do
1273-
do_map_join(t, mapper, joiner, to_binary(mapper.(h)))
1274-
end
1275-
1276-
defp do_map_join([h|t], mapper, joiner, acc) do
1277-
acc = acc <> joiner <> to_binary(mapper.(h))
1278-
do_map_join(t, mapper, joiner, acc)
1279-
end
1280-
1281-
defp do_map_join([], _mapper, _joiner, acc) do
1282-
acc || ""
1283-
end
1284-
1285-
## partition
1286-
1287-
defp do_partition([h|t], fun, acc1, acc2) do
1288-
if fun.(h) do
1289-
do_partition(t, fun, [h|acc1], acc2)
1290-
else
1291-
do_partition(t, fun, acc1, [h|acc2])
1292-
end
1293-
end
1294-
1295-
defp do_partition([], _, acc1, acc2) do
1296-
{ :lists.reverse(acc1), :lists.reverse(acc2) }
1297-
end
1298-
12991251
## sort
13001252

13011253
defp sort_reducer(entry, { :split, y, x, r, rs, bool }, fun) do
@@ -1485,52 +1437,6 @@ defmodule Enum do
14851437

14861438
defp do_zip_next([h|t]), do: { h, t }
14871439
defp do_zip_next([]), do: { nil, [] }
1488-
1489-
## max
1490-
1491-
defp do_max_first([], _) do
1492-
raise Enum.EmptyError
1493-
end
1494-
1495-
defp do_max_first([h|t], fun) do
1496-
do_max(t, fun, h, fun.(h))
1497-
end
1498-
1499-
defp do_max([], _, acc, _) do
1500-
acc
1501-
end
1502-
1503-
defp do_max([h|t], fun, acc, applied_acc) do
1504-
applied = fun.(h)
1505-
if applied > applied_acc do
1506-
do_max(t, fun, h, applied)
1507-
else
1508-
do_max(t, fun, acc, applied_acc)
1509-
end
1510-
end
1511-
1512-
## min
1513-
1514-
defp do_min_first([], _) do
1515-
raise Enum.EmptyError
1516-
end
1517-
1518-
defp do_min_first([h|t], fun) do
1519-
do_min(t, fun, h, fun.(h))
1520-
end
1521-
1522-
defp do_min([], _, acc, _) do
1523-
acc
1524-
end
1525-
1526-
defp do_min([h|t], fun, acc, applied_acc) do
1527-
applied = fun.(h)
1528-
if applied < applied_acc do
1529-
do_min(t, fun, h, applied)
1530-
else
1531-
do_min(t, fun, acc, applied_acc)
1532-
end
1533-
end
15341440
end
15351441

15361442
defimpl Enum.Iterator, for: List do

0 commit comments

Comments
 (0)