こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はElixirの教科書『プログラミングElixir』第8章を読んで、学んだことをまとめます。1
目次
第4章へはこちらから
第5章へはこちらから
第6章へはこちらから
第7章へはこちらから
実行環境
- ・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かで、学ぶことができます。
8.1 マップとキーワードリスト、どちらを使うべきか
辞書型とは、キーと値がペアになったデータ構造。キーワードリストもマップもどちらも辞書型のデータ構造をしている。
8.2 キーワードリスト
キーがアトムであることが条件。キーが2単語以上に渡る場合はダブルクォーテーションで囲む。
(なお、値はどんな型でもよい)
関数に渡されるオプションの目的が多い。
要素の順番に意味がある。キーの重複が許されている。
get/3 関数(keywords, key, default \ nil)
iex()> Keyword.get([a: 1, b: 2, c: 3], :b)
2
iex()> Keyword.get([a: 1, b: 2, c: 3, b: 4], :b)
2 #キーが重複の場合、先にヒットした方が呼び出される
iex()> Keyword.get([a: 1, b: 2, c: 3], :d)
nil #デフォルト値が設定されていない場合でヒットなしの場合
iex()> Keyword.get([a: 1, b: 2, c: 3], :d, 0)
0 #デフォルト値が設定されている場合でヒットなしの場合
iex()> Keyword.get(["apple juice": 110, "banana juice": 220, coffee: 330], :"apple juice", 0)
110 #キーが2単語以上に渡る場合はダブルクォーテーションで囲む
8.3 マップ
要素の順番に意味はない。キーの重複が許されていない。
キーに型指定はない。が、アトムを使用すれば略記やドット記法が使える。
以下の例はキーと値のどちらもがアトムの場合の略記(key: value)を使用している。
第4章の「4.5 マップ(Map)」で書いたものと比べてみてほしい。
drop/2 関数(map, keys)
iex()> map = %{name: "Dave", likes: "Programming", where: "Dallas"} #略記する方が見やすい
%{likes: "Programming", name: "Dave", where: "Dallas"}
iex()> map1 = Map.drop(map, [:where, :likes])
%{name: "Dave"}
#mapマップを直接いじっていない。map1という新しいマップに、mapにdrop/2関数を処理した結果を束縛している
put/3 関数(map, key, value)
iex()> map2 = Map.put(map, :also_likes, "Ruby")
%{also_likes: "Ruby", likes: "Programming", name: "Dave", where: "Dallas"}
#キーワードリストと違い順番が関係ない
8.4 マップのパターンマッチと更新
パターンマッチといえばマップ
iex()> person = %{name: "Dave", height: 1.88}
%{height: 1.88, name: "Dave"}
#:name をキーとするエントリがあるか
iex()> %{name: a_name} = person #マップ内のname:キーに対応する値"Dave"とa_nameを束縛
%{height: 1.88, name: "Dave"} #エントリがある場合の返答
iex()> %{weight: a_weight} = person
** (MatchError) no match of right hand side value: %{height: 1.88, name: "Dave"}
#エントリがない場合の返答(値同士のパターンマッチができないことによるエラー)
iex()> a_name
"Dave"
#:name をキーとするエントリがあるか かつ :height をキーとするエントリもあるか
iex()> %{name: a_name ,height: a_height} = person #nameだけのパターンマッチに加えて、マップ内のheightのパターンマッチも行う
%{height: 1.88, name: "Dave"} #エントリがある場合の返答
8.5 マップの更新
特筆すべき箇所なし
8.6 構造体
構造体とは、変数の型を自由に決められる箱。今回の目的としては、マップの型を示すためにマップを包むモジュール。
#構造体の箱(モジュール)を作る
defmodule Subscriber do
defstruct name: "", paid: false, over_18: true
end
iex()> s1 = %Subscriber{}
%Subscriber{name: "", over_18: true, paid: false} #構造体はマップの「%」と「{」の前にキャメルケースで名前を付ける
iex()> s2 = %Subscriber{name: "Mary", paid: true}
%Subscriber{name: "Mary", over_18: true, paid: true} #箱に値を入れる(デフォルト値と変わらないところは入れなくてよい)
iex()> s3 = %{s2 | name: "Marie"}
%Subscriber{name: "Marie", over_18: true, paid: true} #値の更新は新しいマップになる
8.7 入れ子になった辞書構造体
put_in/2 関数(path, value)
入れ子の内側を呼び出すので、マップのキーはアトムで!(ドット記法で見やすく書こう!)
defmodule School do
defstruct name: "", area: ""
end
defmodule Details do
defstruct category: "", subject: ""
end
defmodule SchoolOrder do
defstruct school: %School{}, details: %Details{}
end
上記を実行した上で、
$ iex defstruct2.exs
iex()> order = %SchoolOrder{school: %School{name: "NishiKokura", area: "Kita"}, details: %Details{category: "SummaryTes
ts", subject: "Math"}} # 入れ子になった辞書構造体の作成
%SchoolOrder{
details: %Details{category: "SummaryTests", subject: "Math"},
school: %School{area: "Kita", name: "NishiKokura"}
}
orderの中身を変更してみる
iex()> put_in(order.school.name, "MinamiKokura")
%SchoolOrder{
details: %Details{category: "SummaryTests", subject: "Math"},
school: %School{area: "Kita", name: "MinamiKokura"} #name: の値をNishiKokuraからMinamikokuraに変更
8.8 セット & 8.9 大いなる力には大いなる誘惑が伴う
MapSetモジュールには型を指定せずに値を複数放り込むことができる。
put/2 関数(map_set, value)
iex()> MapSet.new([1, :two, {"three"}]) #セット(集合)の作成
#MapSet<[1, :two, {"three"}]>
iex()> MapSet.put(MapSet.new([1, :two, {"three"}]), :four) #要素の追加
#MapSet<[1, :four, :two, {"three"}]>
iex()> MapSet.put(MapSet.new([1, :two, {"three"}]), :two) #要素の追加(重複するので追加されないケース)
#MapSet<[1, :two, {"three"}]>
iex()> MapSet.put(MapSet.new([1, :two, {"three"}, :four]), 5.0)
#MapSet<[1, 5.0, :four, :two, {"three"}]> #リストではないので順番は関係ない
~Elixirの国のご案内~
※Elixirって何ぞや?と思ったらこちらもどぞ。未来がぎゅっと詰まった、Elixirは今年で生まれて10周年です
We Are The Alchemists, my friends!2
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽に話しかけてみてください。3
-
プログラミングが完全未経験ゆえ、「え?!そこからつまずく?!!」というお見苦しい箇所があるかと思いますが、私自身の記録のために残します。ご了承ください。 ↩
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩