defmodule Drop do @doc ~S""" Drop Function. Similar to `Stream.drop`, but STRICTLY drops first `n` elements (n > 0). ## Examples iex> Sequences.fibs |> Drop.drop(5) |> Enum.take(5) [8, 13, 21, 34, 55] """ def drop(enum, count) do fun = fn (v, 0) -> {:suspend, v} (_, n) -> {:cont, n - 1} end case Enumerable.reduce(enum, {:cont, count - 1}, fun) do {:halted, _} -> [] {:done, _} -> [] {:suspended, _, next_fun} -> &do_drop(next_fun, &1, &2) end end defp do_drop(_, {:halt, acc}, _fun), do: {:halted, acc} defp do_drop(next, {:suspend, acc}, fun) do {:suspended, acc, &do_drop(next, &1, fun)} end defp do_drop(next, {:cont, acc}, fun) do case next.({:cont, 0}) do {:halted, _} -> {:halted, acc} {:done, _} -> {:done, acc} {:suspended, v, next_fun} -> do_drop(next_fun, fun.(v, acc), fun) end end # fibs from Sequences.ex defp fibs do &fibs({1, 1}, &1, &2) end defp fibs(_, {:halt, acc}, _fun), do: {:halted, acc} defp fibs(v, {:suspend, acc}, fun), do: {:suspended, acc, &fibs(v, &1, fun)} defp fibs({a, b}, {:cont, acc}, fun), do: fibs({b, a + b}, fun.(a, acc), fun) def run do IO.puts "enum0 = fibs |> Stream.map(&IO.inspect/1)" enum0 = fibs |> Stream.map(&IO.inspect/1) IO.puts "enum1 = enum0 |> drop(5)" enum1 = enum0 |> drop(5) IO.puts "enum1 |> Enum.take(5) |> IO.inspect" enum1 |> Enum.take(5) |> IO.inspect IO.puts "enum1 |> Enum.at(5) |> IO.inspect" enum1 |> Enum.at(5) |> IO.inspect end end Drop.run