Elixir 練習問題 ListsAndRecursion-5

次の関数を、ライブラリやリスト内包表記を利用せずに実装しろ、と。

  • all?
  • each
  • filter
  • split
  • take
defmodule MyList do

  def all?([]), do: true
  def all?([head | tail]) when head, do: all?(tail)
  def all?(_list), do: false

  def each([], _func) do
  end
  def each([head|tail], func) do
    func.(head)
    each(tail, func)
  end

  def filter([], _prod) do
    []
  end
  def filter([head|tail], prod) do
    if prod.(head) do
      [head | filter(tail, prod)]
    else
      filter(tail, prod)
    end
  end

  def split(list, n), do: _split({[], list}, n)
  defp _split(result, 0), do: result
  defp _split(result = {_left, []}, _), do: result
  defp _split({left, [head|tail]}, n), do: _split({left ++ [head], tail}, n - 1)

  def take(list, n) do
    {result, _} = split(list, n)
    result
  end

end

順番に行ってみよう。まずは all?

^o^ > iex practice_10_1.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.all?([true, true, true])
true
iex(2)> MyList.all?([true, false, true])
false

つぎに each

iex(3)> MyList.each([1, 2, 3], &IO.puts/1)
1
2
3
nil

nileach 自体の返り値かな。
つぎ、filter

iex(4)> MyList.filter([1, 2, 3, 4, 5], &(&1 > 2))
[3, 4, 5]

split

iex(5)> MyList.split([1, 2, 3, 4, 5], 2)
{[1, 2], [3, 4, 5]}

最後に take

iex(6)> MyList.take([1, 2, 3, 4, 5], 3)
[1, 2, 3]