今回の話
Python エンジニアが Elixir で開発をした約1年間を振り返ってみる(&勉強)。
基本的に他の言語を習得するときと同様、文法の微妙な違いなどが障壁になる程度でしたと言いたいところですが、ちょっと癖がありました。
簡単な自己紹介
- サーバサイドエンジニアとして2012年 gumi に入社
- 携帯ゲームやスマホゲームの開発・運営を2017年12月まで担当
- 2018年から Technical Strategy & Development に配属。新規アプリ開発の支援を行う。
- python2で実装されたフレームワークをベースにpython3版を開発中
- golang でちょろっと既存システムの機能追加やバグ修正したり
- Elixir で新規フレームワーク開発中
キーワード
- return
- パイプライン演算子(まだ書いてない)
- ガード条件
- ドキュメント
- キーワードリストとマップ
for の戸惑いに関しては Qiita の記事に書きましたので省略。
return
ないだと!?
最後に実行された結果が返る。
なので入り組んだ分岐を実装するとぱっと見どこの結果を返す関数か分からなくなります。
関数の処理はできるだけ簡潔に書くよう心がけるようになりました(簡潔なコードが書けたとは言ってない)。
ガード条件
同じ関数名でも「ガード条件」を用いることで関数を呼び出される関数を切り替えられることに面白みを感じました。
関数の処理で分岐があったらこれを用いると関数の中が簡潔になります。
def sample(hoge) do
if is_list(hoge) do
(リストの時の処理)
else
(リストじゃない時の処理)
end
end
これが
def sample(hoge) when is_list(hoge) do
(リストの時の処理)
end
def sample(hoge) do
(リストじゃない時の処理)
end
と書けます。
上から順番にどの関数を呼ぶか判定されるため、順番を入れ替えると hoge がリストなのにリストじゃない時の処理が実行されてしまうので注意が必要です。
ドキュメント
Elixir だから、というわけではなく、私たちが作成したフレームワークをスタジオで使ってもらうためにしっかり書くようになりました。
詳細な記述例も添えることはよくあります。
レビューの際はドキュメントもチェックして指摘をするという取り組みをして、誰が読んでもすぐ使えるように、を心がけてます。
キーワードリストとマップ
python の dict に似ているのですがそれゆえにどうしても頭の中で整理がつかずにいたので、この際この記事で頭の中を整理します。
キーワードリスト
Elixir の連想コレクションです。
[player_id: "1234567890", name: "elixir taro"]
のように、key と value でできたリストです。
値を取り出すときは下記のようにします。
iex> player_data = [player_id: "1234567890", name: "elixir taro"]
iex> player_data[:player_id]
"1234567890"
マップ
Elixir の連想コレクションです!(連想コレクションの書き方が2通りあってまだ馴染めてませんが、今日で克服します)
%{"player_id" => "1234567890", "name" => "elixir taro"}
python の dict の書き方にちょっと似てます。
値を取り出すときは下記のようにします。
iex> player_data = %{"player_id" => "1234567890", "name" => "elixir taro"}
iex> player_data["player_id"]
"1234567890"
マップにはもう一つの書き方があります。
iex> player_data = %{player_id: "1234567890", name: "elixir taro"}
iex> player_data[:player_id]
"1234567890"
iex> player_data.player_id
"1234567890"
=> を使わずに : で key と value を分けます。
python の dict にかなり似た書き方ですが、key は atom です。
頭の中を整理
key の違い
- キーワードリストは atom のみ key にできます。
- マップはどの型も key にできます。
iex> player_data = ["player_id": "1234567890", "name": "elixir taro"]
warning: found quoted keyword "player_id" but the quotes are not required. Note that keywords are always atoms, even when quoted, and quotes should only be used to introduce keywords with foreign characters in them
iex:1
warning: found quoted keyword "name" but the quotes are not required. Note that keywords are always atoms, even when quoted, and quotes should only be used to introduce keywords with foreign characters in them
iex:2
iex> player_data
[player_id: "1234567890", name: "elixir taro"]
このように、キーワードリストで key を文字列にすると warning が表示されて key を atom にしてくれます。
一方、マップは数値を key にすることもできます。
iex> data = %{1 => 1, 2 => 2}
iex> data
%{1 => 1, 2 => 2}
要素の順序保証
- キーワードリストはリストのように順番を保証します
- マップは python の dict のように、順番が保証されません。
iex> player_data = %{player_id: "1234567890", name: "elixir taro"}
iex> player_data
%{name: "elixir taro", player_id: "1234567890"}
以上からまとめると
- 順番の保証をしたい値はキーワードリストを使い、key は atom にする。
- そうでなければマップで OK。
キーワードリストとマップで使える関数は公式ドキュメントをみながら使ってます。
https://hexdocs.pm/elixir/Keyword.html#content
https://hexdocs.pm/elixir/Map.html#content
最後に
約1年間 Elixir での開発を行っておりますが、四苦八苦しながらも楽しんで開発をしております。
特に関数の処理を簡潔に書こうとするのは、なんか自分が実装を綺麗にできているような気がして良い気持ちになれますw(それでもレビューでしこたま指摘されますが、それもまたありがたい)。
まだまだ要領を得ていないものもありますので(例えば Enum.reduce とか)、それはまた別の記事でまとめたいと思います。