ドリコム社さんが開催してくださった【サーバーサイド講義&実技】Elixirハンズオンに参加してきました。そこでの感想やElixirの感想などを書こうと思います。
Elixirとは
Elixirは拡張性と保守性の高いアプリケーションを構築するためにデザインされた、動的で関数型のプログラミング言語です。
https://elixir-lang.jp/
ElixirはErlang VM上で動く言語で、フォールトトレランスやホットスワップが可能なErlangをRuby風の言語で利用しようと設計されたものらしいです。
サーバーサイド言語ではPHPしか扱ったことしかなかった私は、Elixirを使ってみたいなぁと思ってたわけですが、Ruby風の記述がどうも苦手で(つまり{}を使わない言語系)、手こずっている間に色々しないといけないことに追われて後回しになっていたのですが、幸いドリコム社さんのElixir ハンズオンに参加させてもらえることになり参加しました。
やったこと
Elixirはmixというパッケージ管理システムを使ってます。
アプリを新規作成するときは$ mix new test_app
とやります。
こうすることで
test_app
├── README.md
├── config
│ └── config.exs
├── lib
│ └── test_app.ex
├── mix.exs
└── test
├── test_app_test.exs
└── test_helper.exs
と言うような構成になります。
設定ファイルがmix.exs で実際にコードを書くのが lib/test_app.ex らしいです。
mix.exsには依存ライブラリなどの記述をします。
今回のハンズオンでは大量のJSONデータを処理するコードをやりました。
JSONの取扱はPoisonというライブラリを使うらしいのでmix.exsに
defp deps do
[
{:poison, "~> 4.0"},
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
と記述します。
依存関係をダウンロードするためにtest_app $mix deps.get
としてlib/test_app.exのdefmodule test_appの中に
def main do
json_text = File.stream!("d.json")
json_data = Enum.map(data, fn d -> Poison.decode!(d) end)
result = Enum.filter(json_data, fn d -> d["age"] <= 20 end)
Enum.count(result)
end
と書きtest_app/d.jsonを
{"age":39,"name":"aaa"}
{"age":47,"name":"bbb"}
{"age":46,"name":"ccc"}
{"age":13,"name":"ddd"}
{"age":45,"name":"eee"}
{"age":18,"name":"fff"}
{"age":22,"name":"ggg"}
{"age":15,"name":"hhh"}
{"age":24,"name":"iii"}
...
と置きます。
その後、ターミナルにてtest_app $ iex -S mix
iex(1)>test_app.main
と打つと、20歳以下の人数が出てきます。
さて、Elixirにはパイプ演算子というのがあるらしく、前の関数の返数を第一引数として渡したい時に使えるらしいです。上のコードは以下のように書き直せます。
def main do
"d.json"
|> File.stream!
|> Enum.map(fn d -> Poison.decode!(d) end)
|> Enum.filter(fn d -> d["age"] <= 20 end)
|> Enum.count
end
まあ、このように色々教えてもらってEnumじゃなくてStreamやFlow使うと良いよなど教えてもらいました。
感想
Elixir本を読んだときは、「他言語とは違うぞ〜」ということが非常に多く書かれてましたが、ドリコム社さんのおかげでスムーズに理解できました。もちろんElixirの一角だと思いますが、少しずつやっていこうと思います。
ただ、関数っぽい部分とそうでない部分とが妙に突っ掛かると言うか…まあ慣れかな…
あと今回の件で、map=>filterを行いましたが、filter一個でも行けるんじゃないかなと思って少し疑問…具体的には
def is_adult (json_text) do
data = Poison.decode!(json_text)
data["age"] <= 20
end
def main do
"data.json"
|> File.stream!
|> Enum.filter(fn d -> is_adult(d) end)
|> Enum.count
end
て書いても動くのでどうかな〜と、よく分かってない。
まあ、これからボチボチやっていきます。