@@ -760,25 +760,9 @@ defmodule Enum do
760760 @ doc since: "1.12.0"
761761 @ spec count_until ( t , pos_integer ) :: non_neg_integer
762762 def count_until ( enumerable , limit ) when is_integer ( limit ) and limit > 0 do
763- stop_at = limit - 1
764-
765- case Enumerable . count ( enumerable ) do
766- { :ok , value } ->
767- Kernel . min ( value , limit )
768-
769- { :error , module } ->
770- enumerable
771- |> module . reduce (
772- { :cont , 0 } ,
773- fn
774- _ , ^ stop_at ->
775- { :halt , limit }
776-
777- _ , acc ->
778- { :cont , acc + 1 }
779- end
780- )
781- |> elem ( 1 )
763+ case enumerable do
764+ list when is_list ( list ) -> count_until_list ( list , limit , 0 )
765+ _ -> count_until_enum ( enumerable , limit )
782766 end
783767 end
784768
@@ -797,24 +781,10 @@ defmodule Enum do
797781 @ doc since: "1.12.0"
798782 @ spec count_until ( t , ( element -> as_boolean ( term ) ) , pos_integer ) :: non_neg_integer
799783 def count_until ( enumerable , fun , limit ) when is_integer ( limit ) and limit > 0 do
800- stop_at = limit - 1
801-
802- Enumerable . reduce ( enumerable , { :cont , 0 } , fn
803- entry , ^ stop_at ->
804- if fun . ( entry ) do
805- { :halt , limit }
806- else
807- { :cont , stop_at }
808- end
809-
810- entry , acc ->
811- if fun . ( entry ) do
812- { :cont , acc + 1 }
813- else
814- { :cont , acc }
815- end
816- end )
817- |> elem ( 1 )
784+ case enumerable do
785+ list when is_list ( list ) -> count_until_list ( list , fun , limit , 0 )
786+ _ -> count_until_enum ( enumerable , fun , limit )
787+ end
818788 end
819789
820790 @ doc """
@@ -4353,6 +4323,64 @@ defmodule Enum do
43534323 enum |> reduce ( [ ] , & reduce ( & 1 , & 2 , fun ) ) |> :lists . reverse ( )
43544324 end
43554325
4326+ # count_until
4327+
4328+ @ compile { :inline , count_until_list: 3 }
4329+
4330+ defp count_until_list ( [ ] , _limit , acc ) , do: acc
4331+
4332+ defp count_until_list ( [ _head | tail ] , limit , acc ) do
4333+ case acc + 1 do
4334+ ^ limit -> limit
4335+ acc -> count_until_list ( tail , limit , acc )
4336+ end
4337+ end
4338+
4339+ defp count_until_enum ( enumerable , limit ) do
4340+ case Enumerable . count ( enumerable ) do
4341+ { :ok , value } ->
4342+ Kernel . min ( value , limit )
4343+
4344+ { :error , module } ->
4345+ module . reduce ( enumerable , { :cont , 0 } , fn _entry , acc ->
4346+ case acc + 1 do
4347+ ^ limit -> { :halt , limit }
4348+ acc -> { :cont , acc }
4349+ end
4350+ end )
4351+ |> elem ( 1 )
4352+ end
4353+ end
4354+
4355+ @ compile { :inline , count_until_list: 4 }
4356+
4357+ defp count_until_list ( [ ] , _fun , _limit , acc ) , do: acc
4358+
4359+ defp count_until_list ( [ head | tail ] , fun , limit , acc ) do
4360+ if fun . ( head ) do
4361+ case acc + 1 do
4362+ ^ limit -> limit
4363+ acc -> count_until_list ( tail , fun , limit , acc )
4364+ end
4365+ else
4366+ count_until_list ( tail , fun , limit , acc )
4367+ end
4368+ end
4369+
4370+ defp count_until_enum ( enumerable , fun , limit ) do
4371+ Enumerable . reduce ( enumerable , { :cont , 0 } , fn entry , acc ->
4372+ if fun . ( entry ) do
4373+ case acc + 1 do
4374+ ^ limit -> { :halt , limit }
4375+ acc -> { :cont , acc }
4376+ end
4377+ else
4378+ { :cont , acc }
4379+ end
4380+ end )
4381+ |> elem ( 1 )
4382+ end
4383+
43564384 # dedup
43574385
43584386 defp dedup_list ( [ value | tail ] , acc ) do
0 commit comments