   @spec zip(t, t) :: [{any, any}]
   def zip(enumerable1, enumerable2) when is_list(enumerable1)
   and is_list(enumerable2) do
-    do_zip(enumerable1, enumerable2)
+    do_zip(enumerable1, enumerable2, [])
   end
 
   def zip(enumerable1, enumerable2) do


  ## take

  defp do_take([h | t], counter) when counter > 0 do
    [h | do_take(t, counter - 1)]
  end

  defp do_take(_list, 0) do
    []
  end

  defp do_take([], _) do
    []
  end

  ## take_while

  defp do_take_while([h | t], fun) do
    if fun.(h) do
      [h | do_take_while(t, fun)]
    else
      []
    end
  end

  defp do_take_while([], _) do
    []
  end

  ## uniq

  defp do_uniq([h | t], acc, fun) do
    fun_h = fun.(h)
    if Map.has_key?(acc, fun_h) do
      do_uniq(t, acc, fun)
    else
      [h | do_uniq(t, Map.put(acc, fun_h, true), fun)]
    end
  end

  defp do_uniq([], _acc, _fun) do
    []
  end

  ## zip

  defp do_zip([h1 | next1], [h2 | next2]) do
    [{h1, h2} | do_zip(next1, next2)]
  end

  defp do_zip(_, []), do: []
  defp do_zip([], _), do: []

  ## slice


  """
  @spec take_while(t, (element -> as_boolean(term))) :: list
  def take_while(enumerable, fun) when is_list(enumerable) do
    do_take_while(enumerable, fun, [])
  end

  def take_while(enumerable, fun) do
