If performance is something important then there’s also Enum
functions, which get closer to manual recursion as well:
defmodule Mod do
def run(list) do
Enum.chunk_while(list, :start, &chunk_fun/2, &after_fun/1)
end
defp chunk_fun([key, value], :start), do: {:cont, {key, [value]}}
defp chunk_fun([key, value], {key, rest}), do: {:cont, {key, [value | rest]}}
defp chunk_fun([key, value], acc), do: {:cont, emit_acc(acc), {key, [value]}}
defp after_fun({_, _} = acc), do: {:cont, emit_acc(acc), acc}
defp after_fun(acc), do: {:cont, acc}
defp emit_acc({key, list}), do: [key, format(list)]
defp format([el]), do: "#{el}"
defp format([last | rest]), do: "#{rest |> Enum.reverse() |> Enum.join(", ")} and #{last}"
end
Name ips average deviation median 99th %
hissssst 714.47 K 1.40 μs ±2591.76% 1.01 μs 1.71 μs
chunk_while 577.99 K 1.73 μs ±1484.17% 1.35 μs 2.47 μs
Comparison:
hissssst 714.47 K
chunk_while 577.99 K - 1.24x slower +0.33 μs