 
   """
   @spec sort_by(t, (element -> mapped_element),
-    (mapped_element, mapped_element -> boolean))
-    :: list when mapped_element: element
+                (mapped_element, mapped_element -> boolean))
+                :: list when mapped_element: element
 
   def sort_by(enumerable, mapper, sorter \\ &<=/2) when is_function(sorter, 2) do
     enumerable


  """
  @spec split_with(t, (element -> any)) :: {list, list}
  def split_with(enumerable, fun) when is_list(enumerable) and is_function(fun, 1) do
    do_split_with_list(enumerable, fun, [], [])
  end

  def split_with(enumerable, fun) when is_function(fun, 1) do
    do_split_with_enumerable(enumerable, fun)
  end

  defp do_split_with_list([], _fun, acc1, acc2),
    do: {:lists.reverse(acc1), :lists.reverse(acc2)}

  defp do_split_with_list([head | tail], fun, acc1, acc2) do
    if fun.(head) do
      do_split_with_list(tail, fun, [head | acc1], acc2)
    else
      do_split_with_list(tail, fun, acc1, [head | acc2])
    end
  end

  defp do_split_with_enumerable(enumerable, fun) do
    {acc1, acc2} =
      reduce(enumerable, {[], []}, fn(entry, {acc1, acc2}) ->
        if fun.(entry) do

          {acc1, [entry | acc2]}
        end
      end)
    {:lists.reverse(acc1), :lists.reverse(acc2)}
  end

