summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsabiwara <sabiwara@gmail.com>2023-05-08 17:18:19 +0900
committerGitHub <noreply@github.com>2023-05-08 10:18:19 +0200
commitb8770d414d1b67ead1ed02d0f5f13c8a8fba4f27 (patch)
treeecf2461e0c78c6f48aec6bb77197211a5d32bdaa
parente7679429bd6102e2bfe7f55aa2bbbb64e5452923 (diff)
downloadelixir-b8770d414d1b67ead1ed02d0f5f13c8a8fba4f27.tar.gz
Optimize Enum.map/2 for ranges (#12554)
-rw-r--r--lib/elixir/lib/enum.ex24
-rw-r--r--lib/elixir/test/elixir/enum_test.exs3
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