   @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


  def take(enumerable, count) when is_list(enumerable)
  and is_integer(count) and count > 0 do
    do_take(enumerable, count)
  end

  def take(enumerable, count) when is_integer(count) and count > 0 do


  ## take

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

  defp do_take(_list, 0, acc) do
    :lists.reverse(acc)
  end

  defp do_take([], _, acc) do
    :lists.reverse(acc)
  end

  ## take_while

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

  defp do_take_while([], _, acc) do
    :lists.reverse(acc)
  end

  ## uniq

  defp do_uniq([h | t], set, fun, acc) do
    value = fun.(h)
    case set do
      %{^value => true} -> do_uniq(t, set, fun, acc)
      %{} -> do_uniq(t, Map.put(set, value, true), fun, [h | acc])
    end
  end

  defp do_uniq([], _set, _fun, acc) do
    :lists.reverse(acc)
  end

  ## zip

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

  defp do_zip(_, [], acc), do: :lists.reverse(acc)
  defp do_zip([], _, acc), do: :lists.reverse(acc)

  ## slice

