本連載の概要
プログラミングElixirを読んだはいいけどまだまだオブジェクト指向脳が消えず、再帰にもまだ慣れていない、そんな方へ向けた記事です。
特に今までオブジェクト指向の言語ばかり書いていて、関数型言語がはじめてのような場合は再代入が禁止されているから手が止まってしまうことも少なくないと思います。
実際に実務で作成する必要がありそうな関数を作りながらElixirのテストの方法や再帰等を一緒に学んで行けたらと思います。
関数Summary.by_keyを作る
今回作る関数は
date = [
%{"name" => "sato", "script" => "hello"},
%{"name" => "tanaka", "script" => "hello"},
%{"name" => "tanaka", "script" => "hello"},
%{"name" => "kobayashi", "script" => "hello"}
]
上記のようなリストにマップが格納されているdataを指定したキー(今回は"name")でまとめるような関数をElixirで作成したいとします。
[
%{"name" => "sato", "contents" => [%{"script" => "hello"}]},
%{"name" => "tanaka", "contents" => [%{"script" => "hello"}, %{"script" => "hello"}]},
%{"name" => "kobayashi", "contents" => [%{"script" => "hello"}]}
]
なのでキーを"script"にすると
[
%{
"script" => "hello",
"contents" => [
%{"name" => "sato"},
%{"name" => "tanaka"},
%{"name" => "tanaka"},
%{"name" => "kobayashi"}
]
}
]
になるような関数の実装を行います。
関数の引数について検討する
関数の内部仕様を把握しました。
では、下記のA,Bどちらのように実装したほうが良いでしょうか?
Summary.by_key(list,"key") # A
Summary.by_key("key",list) # B
Elixirはパイプ演算子 |>
があるので引数の最初は対象のリストにするのが良いです。
なので上記の場合はAのほうが明らかに良い設計です。
今回はSummary.by_key(list,"key")
と利用できるSummary.by_key/2
を作成していきましょう。
そうすることで下記のような記述が可能となり、実際に関数を利用する際に気持ちよく使うことができます。
origin_data_list
|> maesyori1_function #前処理1
|> Summary.by_key("key")
|> atosyori1_function #後処理1
|> atosyori2_function #後処理2
もしBにしてしまうと、極端な例になるとこんな記述になってしまいます。
atosyori2_function(atosyori1_function(Summary.by_key("key", (maesyori1_function(origin_data_list))))))
一時的に変数などに代入(Elixirなので正確には束縛)するなどで若干可読性は上がるとは思いますが、せっかくですからパイプ演算子を使えるような形で第一引数を設計するのがElixirらしさを生み出します。
まとめ
- 関数を作成するときは引数の順番を意識する
次回に続きます。