         {&Enumerable.reduce(enum, &1, step), [], :cont}
       end)
 
-    do_zip(enum_funs, acc, fun, zip_fun)
-  end
-
-  # This implementation of do_zip/4 works for any number of streams to zip
-  defp do_zip(zips, {:halt, acc}, _fun, _zip_fun) do
+    do_zip_enum(enum_funs, acc, fun, zip_fun)
+  end
+
+  # This implementation of do_zip_enum/4 works for any number of streams to zip
+  defp do_zip_enum(zips, {:halt, acc}, _fun, _zip_fun) do
     do_zip_close(zips)
     {:halted, acc}
   end
 
-  defp do_zip(zips, {:suspend, acc}, fun, zip_fun) do
-    {:suspended, acc, &do_zip(zips, &1, fun, zip_fun)}
-  end
-
-  defp do_zip([], {:cont, acc}, _callback, _zip_fun) do
+  defp do_zip_enum(zips, {:suspend, acc}, fun, zip_fun) do
+    {:suspended, acc, &do_zip_enum(zips, &1, fun, zip_fun)}
+  end
+
+  defp do_zip_enum([], {:cont, acc}, _callback, _zip_fun) do
     {:done, acc}
   end
 
-  defp do_zip(zips, {:cont, acc}, callback, zip_fun) do
+  defp do_zip_enum(zips, {:cont, acc}, callback, zip_fun) do
     try do
-      do_zip_next_tuple(zips, acc, callback, [], [], zip_fun)
+      do_zip_next(zips, acc, callback, [], [], zip_fun)
     catch
       kind, reason ->
         do_zip_close(zips)
         :erlang.raise(kind, reason, __STACKTRACE__)
     else
       {:next, buffer, acc} ->
-        do_zip(buffer, acc, callback, zip_fun)
+        do_zip_enum(buffer, acc, callback, zip_fun)
 
       {:done, _acc} = other ->
         other
     end
   end
 
-  # do_zip_next_tuple/6 computes the next tuple formed by
+  # do_zip_next/6 computes the next tuple formed by
   # the next element of each zipped stream.
-  defp do_zip_next_tuple(
+  defp do_zip_next(
          [{_, [], :halt} | zips],
          acc,
          _callback,

  end

  @doc """
  Lazily zips corresponding elements from a finite collection of enumerables into a new
  enumerable, transforming them with the `zip_fun` function as it goes.


  @spec zip_with(enumerables, (Enumerable.t() -> term)) :: Enumerable.t()
        when enumerables: [Enumerable.t()] | Enumerable.t()
  def zip_with(enumerables, zip_fun) when is_function(zip_fun, 1) do
    if is_list(enumerables) and :lists.all(&is_list/1, enumerables) do
      &zip_list(enumerables, &1, &2, zip_fun)
    else
      &zip_enum(enumerables, &1, &2, zip_fun)
    end
  end

  defp zip_list(_enumerables, {:halt, acc}, _fun, _zip_fun) do
    {:halted, acc}
  end

  defp zip_list(enumerables, {:suspend, acc}, fun, zip_fun) do
    {:suspended, acc, &zip_list(enumerables, &1, fun, zip_fun)}
  end

  defp zip_list(enumerables, {:cont, acc}, fun, zip_fun) do
    case zip_list_heads_tails(enumerables, [], []) do
      {heads, tails} -> zip_list(tails, fun.(zip_fun.(heads), acc), fun, zip_fun)
      :error -> {:done, acc}
    end
  end

  defp zip_list_heads_tails([[head | tail] | rest], heads, tails) do
    zip_list_heads_tails(rest, [head | heads], [tail | tails])
  end

  defp zip_list_heads_tails([[] | _rest], _heads, _tails) do
    :error
  end

  defp zip_list_heads_tails([], heads, tails) do
    {:lists.reverse(heads), :lists.reverse(tails)}
  end

  defp zip_enum(enumerables, acc, fun, zip_fun) do
    step = fn x, acc ->
      {:suspend, :lists.reverse([x | acc])}
    end
