こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はElixirの教科書『プログラミングElixir』第7章を読んで、学んだことをまとめます。1
目次
第4章へはこちらから
第5章へはこちらから
第6章へはこちらから
実行環境
- ・Windows 11 Home(バージョン 21H2, OS ビルド 22000.613)
- ・Ubuntu v18.04 ※WSL2環境下
- ・Elixir v1.13.0 (compiled with Erlang/OTP 24) ※WSL2環境下
- ・Phoenix v1.6.7 ※WSL2環境下
- ・psql (PostgreSQL) 10.19 ※WSL2環境下
以下私が詰まった箇所です。それ以外は本書か
Elixir公式の学習ページか、Elixir Schoolかで、学ぶことができます。
7.1 ヘッドとテイル & 7.2 ヘッドとテイルによるリストの処理
リストはヘッドとそれ以外のテイル。テイルはリスト。再帰的になっている。
※変数の頭に_(アンダースコア)を入れると、その変数がモジュール内で一度も使用されていない場合の警告が出なくなる。
7.3 ヘッドとテイルを使ったリストの構築
,(カンマ)と|(パイプ)記号1つ違うと意味が全く変わるので注意。
# do: の後ろが , になっている場合
def add_1([]), do: []
def add_1([head | tail]), do: [head+1 , add_1(tail)]
#例
def add_1([2, 4, 12])
-> [2+1, add_1([4,12])]
-> [3, [4+1, add_1([12])]]
-> [3, [5, [12+1, add_1[]]]]
-> [3, [5, [13, []]]] #多重リスト(入れ子)になる
# do: の後ろが | になっている場合
def add_1([]), do: []
def add_1([head | tail]), do: [head+1 | add_1(tail)]
#例
=def add_1([2, 4, 12])
-> [2+1 | add_1([4, 12])
-> [3 | [4+1 | add_1([12])]
-> [3 | [5 | [12+1 | add_1[])]]
-> [3 | [5 | [13 | []]]]
-> [3] ++ [5] ++ [13] ++ [] # | はパターンマッチ以外においては ++ (リストの連結)の意味
->[3, 5, 13] #連結リストになる
7.4 map関数の作成
map/2 関数(enumerable, fun)
リストと関数を引数とし、それぞれの要素に関数を適用して、新しいリストを返す。
iex()> Enum.map([1, 2, 3, 4], fn(n) -> n + 1 end)
[2, 3, 4, 5]
iex()> Enum.map([1, 2, 3, 4], fn(n) -> n > 2 end)
[false, false, true, true]
iex()> Enum.map([1, 2, 3, 4], fn(n) -> n + 1 > 2 end)
[false, true, true, true]
iex()> Enum.map([1, 2, 3, 4], fn(n) -> n + 1 >= 2 end)
[true, true, true, true]
#略記するとこんな感じ↓ かっこやendタグの有無は慣れよう。
iex()> Enum.map [1,2,3,4], &(&1+1)
[2, 3, 4, 5]
iex()> Enum.map [1,2,3,4], &(&1) > 2
[false, false, true, true]
iex()> Enum.map [1,2,3,4], &(&1+1) > 2
[false, true, true, true]
iex()> Enum.map [1,2,3,4], &(&1+1) >= 2
[true, true, true, true]
7.5 リストを単一の値にまとめる
reduce/3 関数(enumerable, acc, fun)
初期値(acc)とリスト(enumerable)のヘッドの値に対して関数(fun)を実行し、実行結果を次の初期値とし、リストの次の値を取り出して、同様に関数を実行する。これをリストの末尾に到達するまで再帰的に繰り返す。
iex()> Enum.reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6
7.6 より複雑なリストのパターン
リストのヘッド部は複数の条件を組みあわせることができる。
@doc """
paramater swap.
## Examples
iex> Practice.swap([])
[]
iex> Practice.swap([2, 4, 6, 8])
[4, 2, 8, 6]
"""
def swap([]), do: []
#空のリストが渡された時はそれをそのまま出力する。
def swap([a, b | tail]), do: ([b, a | swap(tail)])
#要素がa, b のペア、つまり、要素数が偶数個のリストが渡された時はそれをそのまま出力する。
def swap(_), do: raise "Can't swap a list with an odd number of elements"
#それ以外、つまり、要素数が奇数個のリストが渡されたときは続くエラーメッセージを出力する。
# ** (RuntimeError) Can't swap a list with an odd number of elementsというエラーメッセージが返ってくるのが期待値
7.7 実践Listモジュール & 7.8 リストと仲良くなろう
Elixirに標準組み込み済みのListモジュール。公式ドキュメントはこちらから
flatten/1 (list)関数
平滑化 = 多重リストの入れ子をなくす。
iex()> List.flatten([100, [200, 300, [400, 500], [600]]])
[100, 200, 300, 400, 500, 600]
replace_at/3 (list, index, value) 関数
リスト内のindexが条件と一致する場所にある要素を置き換える。
indexは0から始まる(つまり、要素の2番目はインデックス的には1)
iex()> list = [1, 2, 3]
[1, 2, 3]
iex()> List.replace_at(list, 2, "buckle my shoe")
[1, 2, "buckle my shoe"]
keyfind/3 (list, key, position, default \ nil)関数
positionにおけるkeyが条件が最初に一致したタプルを返す。
positionはタプル内におけるindexみたいなものか?
iex()> kw = [{:name, "Dave"}, {:likes, "Programming"}, {:where, "Dallas", "TX"}]
[{:name, "Dave"}, {:likes, "Programming"}, {:where, "Dallas", "TX"}]
iex()> List.keyfind(kw, :likes, 0)
{:likes, "Programming"}
iex()> List.keyfind(kw, "Dallas", 1)
{:where, "Dallas", "TX"}
iex()> List.keyfind(kw, "TX", 2)
{:where, "Dallas", "TX"}
iex()> List.keyfind(kw, "Dallas", 2) #position2に存在するkeyが条件と一致しない
nil
~Elixirの国のご案内~
※Elixirって何ぞや?と思ったらこちらもどぞ。未来がぎゅっと詰まった、Elixirは今年で生まれて10周年です
We Are The Alchemists, my friends!2
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽に話しかけてみてください。3
-
プログラミングが完全未経験ゆえ、「え?!そこからつまずく?!!」というお見苦しい箇所があるかと思いますが、私自身の記録のために残します。ご了承ください。 ↩
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩