diff options
author | sabiwara <sabiwara@gmail.com> | 2023-05-08 17:18:19 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-08 10:18:19 +0200 |
commit | b8770d414d1b67ead1ed02d0f5f13c8a8fba4f27 (patch) | |
tree | ecf2461e0c78c6f48aec6bb77197211a5d32bdaa | |
parent | e7679429bd6102e2bfe7f55aa2bbbb64e5452923 (diff) | |
download | elixir-b8770d414d1b67ead1ed02d0f5f13c8a8fba4f27.tar.gz |
Optimize Enum.map/2 for ranges (#12554)
-rw-r--r-- | lib/elixir/lib/enum.ex | 24 | ||||
-rw-r--r-- | lib/elixir/test/elixir/enum_test.exs | 3 |
2 files changed, 26 insertions, 1 deletions
diff --git a/lib/elixir/lib/enum.ex b/lib/elixir/lib/enum.ex index b5931af10..bdc83a20e 100644 --- a/lib/elixir/lib/enum.ex +++ b/lib/elixir/lib/enum.ex @@ -1693,6 +1693,10 @@ defmodule Enum do :lists.map(fun, enumerable) end + def map(first..last//step, fun) do + map_range(first, last, step, fun) + end + def map(enumerable, fun) do reduce(enumerable, [], R.map(fun)) |> :lists.reverse() end @@ -4033,7 +4037,13 @@ defmodule Enum do ## Helpers - @compile {:inline, entry_to_string: 1, reduce: 3, reduce_by: 3, reduce_enumerable: 3} + @compile {:inline, + entry_to_string: 1, + reduce: 3, + reduce_by: 3, + reduce_enumerable: 3, + reduce_range: 5, + map_range: 4} defp entry_to_string(entry) when is_binary(entry), do: entry defp entry_to_string(entry), do: String.Chars.to_string(entry) @@ -4332,6 +4342,18 @@ defmodule Enum do join_non_empty_list(rest, joiner, [joiner, entry_to_string(first) | acc]) end + ## map + + defp map_range(first, last, step, fun) + when step > 0 and first <= last + when step < 0 and first >= last do + [fun.(first) | map_range(first + step, last, step, fun)] + end + + defp map_range(_first, _last, _step, _fun) do + [] + end + ## map_intersperse defp map_intersperse_list([], _, _), diff --git a/lib/elixir/test/elixir/enum_test.exs b/lib/elixir/test/elixir/enum_test.exs index 4b41d2281..066ec0e9d 100644 --- a/lib/elixir/test/elixir/enum_test.exs +++ b/lib/elixir/test/elixir/enum_test.exs @@ -1861,6 +1861,9 @@ defmodule EnumTest.Range do test "map/2" do assert Enum.map(1..3, fn x -> x * 2 end) == [2, 4, 6] assert Enum.map(-1..-3, fn x -> x * 2 end) == [-2, -4, -6] + assert Enum.map(1..10//2, fn x -> x * 2 end) == [2, 6, 10, 14, 18] + assert Enum.map(3..1//-2, fn x -> x * 2 end) == [6, 2] + assert Enum.map(0..1//-1, fn x -> x * 2 end) == [] end test "map_every/3" do |