summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@dashbit.co>2023-05-07 11:52:20 +0200
committerJosé Valim <jose.valim@dashbit.co>2023-05-07 11:52:20 +0200
commit27393a6f2b75e6cc24c84cf996b15b8694a6f9c2 (patch)
treea30ceb21f953b4acab93d0beb8eadd1fe2d0cd2e
parentf4a77c5794f598f0ec3e4bb3267131fdda6d8a65 (diff)
downloadelixir-27393a6f2b75e6cc24c84cf996b15b8694a6f9c2.tar.gz
Optimize any? and all? for ranges
-rw-r--r--lib/elixir/lib/enum.ex56
1 files changed, 34 insertions, 22 deletions
diff --git a/lib/elixir/lib/enum.ex b/lib/elixir/lib/enum.ex
index b75f5cae0..ab7828d72 100644
--- a/lib/elixir/lib/enum.ex
+++ b/lib/elixir/lib/enum.ex
@@ -368,7 +368,11 @@ defmodule Enum do
"""
@spec all?(t, (element -> as_boolean(term))) :: boolean
def all?(enumerable, fun) when is_list(enumerable) do
- all_list(enumerable, fun)
+ predicate_list(enumerable, true, fun)
+ end
+
+ def all?(%Range{first: first, last: last, step: step}, fun) do
+ predicate_range(first, last, step, true, fun)
end
def all?(enumerable, fun) do
@@ -429,7 +433,11 @@ defmodule Enum do
"""
@spec any?(t, (element -> as_boolean(term))) :: boolean
def any?(enumerable, fun) when is_list(enumerable) do
- any_list(enumerable, fun)
+ predicate_list(enumerable, false, fun)
+ end
+
+ def any?(%Range{first: first, last: last, step: step}, fun) do
+ predicate_range(first, last, step, false, fun)
end
def any?(enumerable, fun) do
@@ -4132,7 +4140,7 @@ defmodule Enum do
## Implementations
- ## all?
+ ## all?/1
defp all_list([h | t]) do
if h do
@@ -4146,19 +4154,7 @@ defmodule Enum do
true
end
- defp all_list([h | t], fun) do
- if fun.(h) do
- all_list(t, fun)
- else
- false
- end
- end
-
- defp all_list([], _) do
- true
- end
-
- ## any?
+ ## any?/1
defp any_list([h | t]) do
if h do
@@ -4172,16 +4168,32 @@ defmodule Enum do
false
end
- defp any_list([h | t], fun) do
- if fun.(h) do
- true
+ ## any?/2 all?/2
+
+ defp predicate_list([h | t], initial, fun) do
+ if !!fun.(h) == initial do
+ predicate_list(t, initial, fun)
else
- any_list(t, fun)
+ not initial
end
end
- defp any_list([], _) do
- false
+ defp predicate_list([], initial, _) do
+ initial
+ end
+
+ defp predicate_range(first, last, step, initial, fun)
+ when step > 0 and first <= last
+ when step < 0 and first >= last do
+ if !!fun.(first) == initial do
+ predicate_range(first + step, last, step, initial, fun)
+ else
+ not initial
+ end
+ end
+
+ defp predicate_range(_first, _last, _step, initial, _fun) do
+ initial
end
## concat