diff options
author | José Valim <jose.valim@dashbit.co> | 2023-05-07 11:52:20 +0200 |
---|---|---|
committer | José Valim <jose.valim@dashbit.co> | 2023-05-07 11:52:20 +0200 |
commit | 27393a6f2b75e6cc24c84cf996b15b8694a6f9c2 (patch) | |
tree | a30ceb21f953b4acab93d0beb8eadd1fe2d0cd2e | |
parent | f4a77c5794f598f0ec3e4bb3267131fdda6d8a65 (diff) | |
download | elixir-27393a6f2b75e6cc24c84cf996b15b8694a6f9c2.tar.gz |
Optimize any? and all? for ranges
-rw-r--r-- | lib/elixir/lib/enum.ex | 56 |
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 |