호두나무 공방/Exercism in Elixir

Strain - Exercism in Elixir

2022. 4. 14. 23:28

문제 보기

명제(predicate)가 참일 때, 또는 거짓일 때 리스트의 항목을 필터링하는 keepdiscard 함수를 구현하는 문제였다. ...다시 말해 Enum.filter, reject 두 함수를 구현하는 문제였다. 기본 제공되는 기능들을 직접 구현하는 과제는 여러 번 해본 터라, 이번에도 큰 어려움이 없었다.

defmodule Strain do
  @doc """
  Given a `list` of items and a function `fun`, return the list of items where
  `fun` returns true.

  Do not use `Enum.filter`.
  """
  @spec keep(list :: list(any), fun :: (any -> boolean)) :: list(any)
  def keep(list, fun) do
    do_keep(list, fun, [])
  end

  defp do_keep([], _, acc), do: Enum.reverse(acc)
  defp do_keep([h | t], fun, acc) do
    new_acc = if fun.(h), do: [h | acc], else: acc
    do_keep(t, fun, new_acc)
  end

  @doc """
  Given a `list` of items and a function `fun`, return the list of items where
  `fun` returns false.

  Do not use `Enum.reject`.
  """
  @spec discard(list :: list(any), fun :: (any -> boolean)) :: list(any)
  def discard(list, fun) do
    do_discard(list, fun, [])
  end

  defp do_discard([], _, acc), do: Enum.reverse(acc)
  defp do_discard([h | t], fun, acc) do
    new_acc = if fun.(h), do: acc, else: [h | acc]
    do_discard(t, fun, new_acc)
  end
end