あまりドキュメントの確認の仕方って理解できていないかも。来週の勉強会で質問してみようかな。ともあれ、10 章の Enum と Stream 確認開始。
Enum
なかなか凄い。コード例眺めてるだけで面白い。
ListsAndRecursion-5
ひとまず all? から検討着手。例を確認してみます。
iex(1)> list = Enum.to_list 1..5
[1, 2, 3, 4, 5]
iex(2)> Enum.all?(list, &(&1 < 4))
false
以下をでっちあげたのですがコンパイルできない。
defmodule MyEnum do
def all?([], _func), do: true
def all?([head | tail], func) do
if func(head) do
all?(tail, func)
else
false
end
end
end
func の呼び出し方法がダウトでした。正しくは以下。
if func.(head) do
all?(tail, func)
一応うまく動いてはいるみたい。次は each とのこと。each て何だ。ググッてみるに以下な用例とのこと。
iex(11)> Enum.each list, &IO.puts(&1)
1
2
3
4
5
:ok
最初以下な手続き渡してたら :ok しか戻ってこず。
Enum.each list, &(&1 + 1)
これは以下なカンジで良いのかどうか。
def each([], _func), do: :ok
def each([head | tail], func) do
func.(head)
each(tail, func)
end
こんな書き方できるのかしら。できるみたい、動きました。次は filter とのこと。例示されているのは以下。
iex(15)> require Integer
Integer
iex(16)> Enum.filter list, &Integer.is_even/1
[2, 4]
これも all? のパターンなのかな。
def filter([], func), do: true
def filter([head | tail], func) do
if func.(head) do
filter(tail, func)
else
false
end
end
間違えた。true になる要素をリストにして戻すのでした。
def filter([], func), do: []
def filter([head | tail], func) do
if func.(head) do
[head | func.(tail)]
else
func.(tail)
end
end
で、書き換えてコンパイルしてるのですが、実行結果が変わらず。なんだこれ。って思ったら func 呼び出してるじゃん何してるのorz
def filter([head | tail], func) do
if func.(head) do
[head | filter(tail, func)]
else
filter(tail, func)
end
end
とほほ。焦って書くとロクなことないスね。次は split です。
iex(9)> MyEnum.filter list, &Integer.is_even/1
[2, 4]
iex(10)> Enum.split list, 3
{[1, 2, 3], [4, 5]}
カウントすりゃいいのかな。
def split([head | tail], end) do: split([head | tail], end, 0, [])
defp _split([], end, count, list), do: list
defp _split([head | tail], end, count, list) do
if count > end do
[list | tail]
else
_split(tail, end, count + 1, [list | [head | []]])
end
end
なんだろう、コンパイルエラーがある、って言われるのですが原因不明。。開き括弧が閉じていないと。こうしても同じですね。
def split(list, end) do
_split(list, end, 0, [])
end
defp _split([], end, count, list), do: list
defp _split([head | tail], end, count, list) do
if count > end do
[list | tail]
else
_split(tail, end, count + 1, [list | [head | []]])
end
end
上二つの手続き定義を消しても同じエラーが出ますね。
む
わかったorz end
が予約語なのかorz そして実行してみたら駄目なナニがorz なんか根本的に色々間違えてる感満点ですねorz
最初がマズい
head をおしりに追加、ってのがアレなんですよね。[head]
を、なのか。最初がアレなんですが。つうか、色々確認してみるに戻ってきてるの何だろ。
iex(24)> Enum.split list, 10
{[1, 2, 3, 4, 5], []}
この {
って何なのかと。つうか前のページ見てみれば ++
って演算子がありますね。
def split(l, term), do: _split(l, term, 1, [])
defp _split([], term, c, l), do: {l, []}
defp _split([head | tail], term, c, l) do
if c < term do
_split(tail, term, c + 1, l ++ [head])
else
[l | [[head | tail]]]
end
end
出力が微妙に違いますがヨシってことにします (を
take
ようやく最後だ。例示されてる実行例が以下?
iex(38)> Enum.take(list, 3)
[1, 2, 3]
これは split の前半を戻せば良いので簡単すね。
def take(l, term), do: _take(l, term, 1, [])
defp _take([], term, c, l), do: l
defp _take([head | tail], term, c, l) do
if c > term do
l
else
_take(tail, term, c + 1, l ++ [head])
end
end
条件式に微妙さを感じております。