diff options
author | José Valim <jose.valim@plataformatec.com.br> | 2019-08-15 11:56:32 +0200 |
---|---|---|
committer | José Valim <jose.valim@plataformatec.com.br> | 2019-08-15 11:56:32 +0200 |
commit | 3ae4ef7c03bc4eb7c1d37820b1475a6592067575 (patch) | |
tree | 2add36f46a1a1f4374fc39b8b77176c554ff27c0 | |
parent | 4477115675f52b9b4234f974765aaaeb7036bbed (diff) | |
download | elixir-3ae4ef7c03bc4eb7c1d37820b1475a6592067575.tar.gz |
Do not traverse the list if we are keeping the whole tail, closes #9274
-rw-r--r-- | lib/elixir/lib/enum.ex | 24 | ||||
-rw-r--r-- | lib/elixir/lib/map_set.ex | 3 |
2 files changed, 18 insertions, 9 deletions
diff --git a/lib/elixir/lib/enum.ex b/lib/elixir/lib/enum.ex index 5bc554865..2f35c50e6 100644 --- a/lib/elixir/lib/enum.ex +++ b/lib/elixir/lib/enum.ex @@ -3075,7 +3075,7 @@ defmodule Enum do end defp slice_any(list, start, amount) when is_list(list) do - Enumerable.List.slice(list, start, amount) + list |> drop_list(start) |> take_list(amount) end defp slice_any(enumerable, start, amount) do @@ -3108,7 +3108,8 @@ defmodule Enum do end defp slice_count_and_fun(enumerable) when is_list(enumerable) do - {length(enumerable), &Enumerable.List.slice(enumerable, &1, &2)} + length = length(enumerable) + {length, &Enumerable.List.slice(enumerable, &1, &2, length)} end defp slice_count_and_fun(enumerable) do @@ -3122,7 +3123,7 @@ defmodule Enum do {:cont, {[elem | acc], count + 1}} end) - {count, &Enumerable.List.slice(:lists.reverse(list), &1, &2)} + {count, &Enumerable.List.slice(:lists.reverse(list), &1, &2, count)} end end @@ -3324,10 +3325,16 @@ defimpl Enumerable, for: List do def reduce([head | tail], {:cont, acc}, fun), do: reduce(tail, fun.(head, acc), fun) @doc false - def slice([], _start, _count), do: [] - def slice(_list, _start, 0), do: [] - def slice([head | tail], 0, count), do: [head | slice(tail, 0, count - 1)] - def slice([_head | tail], start, count), do: slice(tail, start - 1, count) + def slice([], _start, _count, _size), do: [] + def slice(_list, _start, 0, _size), do: [] + def slice(list, start, count, count), do: list |> drop(start) + def slice(list, start, count, _size), do: list |> drop(start) |> take(count) + + defp drop(list, 0), do: list + defp drop([_ | tail], count), do: drop(tail, count - 1) + + defp take(_list, 0), do: [] + defp take([head | tail], count), do: [head | take(tail, count - 1)] end defimpl Enumerable, for: Map do @@ -3344,7 +3351,8 @@ defimpl Enumerable, for: Map do end def slice(map) do - {:ok, map_size(map), &Enumerable.List.slice(:maps.to_list(map), &1, &2)} + size = map_size(map) + {:ok, size, &Enumerable.List.slice(:maps.to_list(map), &1, &2, size)} end def reduce(map, acc, fun) do diff --git a/lib/elixir/lib/map_set.ex b/lib/elixir/lib/map_set.ex index 13b63df77..92cbdc45c 100644 --- a/lib/elixir/lib/map_set.ex +++ b/lib/elixir/lib/map_set.ex @@ -378,7 +378,8 @@ defmodule MapSet do end def slice(map_set) do - {:ok, MapSet.size(map_set), &Enumerable.List.slice(MapSet.to_list(map_set), &1, &2)} + size = MapSet.size(map_set) + {:ok, size, &Enumerable.List.slice(MapSet.to_list(map_set), &1, &2, size)} end def reduce(map_set, acc, fun) do |