Elixir勉強会で使った資料を公開します！【Erlang＆Elixir fest 2019 レポート付き】

面白法人カヤックのKoyoです！先日社内勉強会で**Elixir勉強会**を行ったので、みなさんがElixirを広める際に参考になればと思い、資料を公開します！
6/1に開催された[Erlang＆Elixir fest 2019](https://elixir-fest.jp/)のレポート付きです！
（開催者・講演者の方にこの場を借りて感謝を述べさせていただきます）

**後半のハンズオンで使うので以下の環境構築を先に済ませておくことを強くオススメします！（`brew install elixir` が長い！！）**
https://github.com/ohr486/ErlangElixirFestHandsOn2019/wiki/1-%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89#1-1-%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89

---

# ~ Elixir入門 ~ 20190607
## 目次
- |> Elixir って何？
- |> GoとElixirのコードを比較してみる
- |> 「Erlang & Elixir fest 2019」 レポート
- |> Elixir ハンズオン！
- |> まとめ
- |> もっと学びたい人へ

## Elixirって何？
Elixirの[wiki](https://ja.wikipedia.org/wiki/Elixir_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E))より
> Elixir (エリクサー) は並行処理の機能や関数型といった特徴を持つ、Erlangの仮想マシン (BEAM) 上で動作するコンピュータプログラミング言語である。ElixirはErlangで実装されているため、分散システム、耐障害性、ソフトリアルタイムシステム等の機能を使用することができるが、拡張機能として、マクロを使ったメタプログラミング、そしてポリモーフィズムなどのプログラミング・パラダイムもプロトコルを介して実装されている

ここでElixirはErlangという言語で実装されているという記述がありますが、Erlangの説明は以下です

Erlangの[wiki](https://ja.wikipedia.org/wiki/Erlang)より
> Erlang（アーラン）は、コンピュータにおいて汎用的な用途に使うことができる並行処理指向のプログラミング言語および実行環境

> Erlangはエリクソンにより次の条件のシステムを構築できるよう設計された。
> * 分散化された環境
> * 障害に耐性をもつ (フォルトトレラント)
> * ある程度のリアルタイム性を備える
> * 無停止で稼働する

> ホットスワップが可能であり、稼働中のシステムを停止すること無くErlangのプログラムを変更することができる

※ちなみにErlangを知らなくてもElixirは書けます

さらにElixirには以下の強力なフレームワークがあります
- Railsの開発メンバーによって開発された、RailsライクなWebフレームワーク [**「Phoenix」**](https://phoenixframework.org/)
- 近年台頭してきた組み込み/IoT向けのフレームワーク[**「Nerves」**](https://nerves-project.org/)

また、私が所属しているfukuoka.exでは[Elixirの特徴を以下のように述べています](https://fukuokaex.connpass.com/event/131678/)
> 一般的に「関数型言語」と言えば、言語の習得が難しく、組織として選定しづらいイメージがありますが、Elixirは、言語仕様や構文がシンプルかつ簡単なので、「育成や習得の容易性」を切り捨てること無く、関数型のメリットも享受できます

> 関数型のメリットは、以下の通りです

> * 状態が無いことで、同じ入力を何度行っても同じ出力しか返さないので、意図しない挙動にならない
> * 変数がイミュータブル（作成後にその状態が不変）なので、マルチスレッドや並行処理で競合しない
> * プログラム構造が小さな関数群で構成され、シンプルに保たれるため、変更容易性が向上する
少ないコードで、凝縮度の高い高度な処理が書ける
> * リスト設計に慣れていくと、他言語で数百行かかる複雑な処理も、数行のコードで組むことが可能になる
> * できあがったコードは、オブジェクト指向言語の1/100の量になることもあり、見た目も100倍エレガント
> * オブジェクト指向言語経験者の移行は大変（関数型全般に言える）だが、移行後は、何倍も生産性が高まる

> 更に、「Elixirならでは」の以下メリットも上乗せされます

> * 習得がカンタンなので、プログラミング経験が無い入門者・初級者向け
> * 関数の引数でのパターンマッチが可能で、呼出時の事前条件チェックや関数呼び分けには、快感すら感じる
> * JSONパースが得意なので、Google APIやBacklog API等、様々なWeb APIとの連携に強い
> * マルチコアCPUを簡単にフル活用できる
> * マルチクラスタ（AWS、GCP、Azure）のスケールアウトも楽々実現
> * 長期間の安定運用を実現してきた「Erlang VM」の元で動作する
> * データ変換とバイナリデータ検索に特化しているので、ファイルヘッダ解析やIoT／ドローン制御にも向いている

ちなみに私はElixirのコミュニティ「fukuoka.ex」にて[高速フーリエ変換(FFT)のライブラリ](https://github.com/koyo-miyamura/ex_fft)書いたり、[Qiita記事](https://qiita.com/koyo-miyamura/items/86f1148e4a8a7c591e55)書いたりしています

※実はカヤックのテックブログにも[めっちゃ詳しい記事](https://techblog.kayac.com/elixir_for_rubyists)があります笑

## GoとElixirのコードを比較してみる
Elixirの雰囲気を感じてみるために、ここでGoとElixirのコードを比較してみたいと思います(どちらが優れているかではなく、純粋に文法の比較をしていきたいと思います)

### 引数2つを受け取って積が偶数か奇数かを判定する

#### Go

```go
package product

func product(a, b int) string {
	if product := a * b; product%2 == 0 {
		return "Even"
	}
	return "Odd"
}
```

```go
package product

import "testing"

func Test_product(t *testing.T) {
	tests := []struct {
		a    int
		b    int
		want string
	}{
		{
			a:    3,
			b:    4,
			want: "Even",
		},
		{
			a:    1,
			b:    21,
			want: "Odd",
		},
	}
	for _, tt := range tests {
		t.Run("test", func(t *testing.T) {
			if got := product(tt.a, tt.b); got != tt.want {
				t.Errorf("product() = %v, want %v", got, tt.want)
			}
		})
	}
}
```

#### Elixir

```elixir
defmodule AtcoderPractice do
  @doc """
  ## Examples

      iex> AtcoderPractice.product(3,4)
      'Even'

      iex> AtcoderPractice.product(1,21)
      'Odd'

  """
  def product(a, b) do
    case rem(a * b, 2) do
      0 ->
      'Even'

      1 ->
      'Odd'
    end
  end
end
```

```elixir
defmodule AtcoderPracticeTest do
  use ExUnit.Case
  doctest AtcoderPractice
end
```

※Elixirはdoctestが標準ライブラリに実装されているため、対話的実行環境(iex)の実行結果を書くことでテストできます

ちなみにElixirは関数でパターンマッチできるので、もっとシンプルに書けます

```elixir
  def product(a, b) do
    (a * b)
    |> rem(2)
    |> determine()
  end

  def determine(0), do: 'Even'
  def determine(1), do: 'Odd'
```

### "1"または"0"を並べた文字列に"1"がいくつ含まれるか判定
例:
- "101" -> 2
- "010" -> 1

※テスト省略

#### Go

```go
func countOne(a string) int {
	count := 0
	for i := 0; i < len(a); i++ {
		if a[i] == '1' {
			count++
		}
	}
	return count
}
```

#### Elixir

```elixir
def count_one(s) do
  s |> String.codepoints() |> Enum.count(fn x -> x == "1" end)
end
```

※Elixirでは計算結果を次の関数に伝えるためにパイプ `|>` が使えます．bashのパイプ `|` と似たような感じです．

---

他の例を見たい方は同じ問題をGoとElixirでそれぞれ解いた記事を書いたので、比較してみてください！

- [AtCoder 過去問精選 10 問 をGoでやってみた](https://qiita.com/koyo-miyamura/items/17ddf9aa70fb1479e6eb)
- [【doctestつき】AtCoder に登録したら解くべき精選過去問 10 問を"Elixir"で解いてみた](https://qiita.com/koyo-miyamura/items/9f224a3e56ea75939dca)


## Erlang & Elixir fest 2019 レポート
6/1に開催された[「Erlang & Elixir fest 2019」](https://elixir-fest.jp/)に行ってきました！
当日は多彩な発表がありましたが、プロダクション環境での採用事例を中心にいくつか紹介していきたいと思います

### ロマサガRS における Elixir サーバー開発実践 \~生産性を上げてゲームの面白さに注力\~

アカツキさんによるゲームサーバでElixirを導入した事例です[1]

静的解析ツールであるDialyzerを導入した開発方針やインフラ構成など貴重なプロダクション導入事例が述べられていました

- [1] [ロマサガRS における Elixir サーバー開発実践 \~生産性を上げてゲームの面白さに注力\~](https://speakerdeck.com/elixirfest/romasakars-niokeru-elixir-sahakai-fa-shi-jian-sheng-chan-xing-woshang-ketekemufalsemian-bai-sanizhu-li)

発表ではPhoenixを使っていないとのことでしたが、質疑応答で「Phoenixを使わなかった理由はなぜか」という質問があり、回答としては「当時はPhoenixが成熟していなかったため。今なら使うだろう」とのことでした

### XFLAG × スポーツ × Elixir
mixiさんによる Elixir のプロダクション導入事例

インフラ構成や技術選定理由について詳しく述べていました

- [2] [XFLAG × スポーツ × Elixir](https://speakerdeck.com/mixi_engineers/xflag-x-supotu-x-elixir)

特に Protocol Buffers を Elixir で導入する事例はあまり知られていないのでは無いかと思います

### その他
北九大の山崎先生の発表[3]や京都大学の高瀬先生の発表[4]などアカデミックな発表もいくつか

その中でElixirの海外カンファレンスであるElixir conf 2019 について触れていましたが、海外ではWebフレームワークの「Phoenix」と並んで「Nerves」というIoTフレームワークが台頭しているとのことで、要注目でした

- [3] [超並列高速実行処理系 Hastega 〜 Lonestar ElixirConf 凱旋帰国](https://speakerdeck.com/zacky1972/chao-bing-lie-gao-su-shi-xing-chu-li-xi-hastega-heisuga-lonestar-elixirconf-kai-xuan-gui-guo)
- [4] [Nervesが開拓する「ElixirでIoT」の新世界](https://www.slideshare.net/takasehideki/nerveselixiriot)

※ElixirではなくErlangですが、任天堂の渡邉さんの発表[5]は必見です！

- [5] [Erlang/OTP と ejabberd を活用した Nintendo Switch（TM）向けプッシュ通知システム「NPNS」の開発事例](https://speakerdeck.com/elixirfest/otp-to-ejabberd-wohuo-yong-sita-nintendo-switch-tm-xiang-ke-hutusiyutong-zhi-sisutemu-npns-false-kai-fa-shi-li)

その他にも魅力的な発表がたくさんありました！資料は公開されていることが多いので是非眺めてみてください！

なんと[めっちゃ網羅的なスライドまとめ記事](https://qiita.com/snamiki1212/items/1237b75444e5742c9928)を作ってくれた人がいるので、こちらから探してみてください！

---

Elixirを採用している企業として、日本ではアカツキやgumiやmixiなどが挙げられます

特にgumiさんに至っては過去に「Elixirメインで開発する」という宣言までした力の入れっぷり

[Elixir Conf Japan 2017 レポート | gumi TECH Blog](https://recruit.gu3.co.jp/engineering/event/elixir-conf-japan-2017/)
> そしてこの日、会場が最もどよめいたのが、幾田が「gumiは、Erlang ＋ pythonの会社からElixirへ移行し、Erlangによる既存資産（※弊社のソーシャルゲーム開発における共通基盤）を全部Elixirにリプレイスします。今後、Erlangによる新規の開発をやめます！」と発表した瞬間。弊社のCTOとしての突然の決意表明に、会場からは驚きの声があがりました

ちなみに世界に目を向けると実は[「Discord」](https://blog.discordapp.com/scaling-elixir-f9b8e1e7c29b)でも使われていたり！

## Elixir ハンズオン！
「Elixir fest 2019」で行われた Elixir 体験ハンズオンをやってみましょう！

Elixirが得意とする並列処理を15分程度で体験できる内容になっています！

https://github.com/ohr486/ErlangElixirFestHandsOn2019/wiki

## まとめ
私がこの１年でElixirを触ったりウォッチしてみた所感は以下です（個人の感想）

- モナドとか知らなくても使える関数型なのでキャッチアップしやすい
- 関数型の考え方に慣れるまでやや苦労するが、コードがとてもシンプルになる
- 今後シングルコアの動作周波数が向上しないことを踏まえると、CPUのマルチコアを活かせるのは強い
- PhoenixがRailsの良さを保ちつつ高速なので今後台頭しそう
- とはいえプロダクション環境での実績はまだまだ
- 今後マルチコアを活かせるElixirが台頭してきそうなので、触っておいて損はない

私は今後も継続的にElixirをやっていこうと思いますので、一緒にやっていきましょう！

## もっとElixir学びたい人へ
- どんなコミュニティがあるの？
  - [fukuoka.ex](https://fukuokaex.connpass.com/) 月に1回程度のペースでもくもく会やってます(リモート参加大歓迎)
  - [Shinjuku.ex](https://shinjukuex.connpass.com/) 都内もくもく会を行っているElixirコミュニティ
  - [tokyo.ex](https://beam-lang.connpass.com/)
- いい感じの発表スライドある？
  - 個人的には fukuoka.ex 代表 [piacere さんが執筆したスライド](https://speakerdeck.com/piacere)がオススメです．他言語と比較したElixirの良さを歴史的経緯を踏まえて述べています
- Elixirの文法を知りたい
  - [Elixir公式ガイド（日本語）](https://elixir-lang.jp/)
  - [Elixir公式ガイド（英語）](https://elixir-lang.org/) 日本語情報古い場合があるのでこちらも
  - [Elixir School(日本語)](https://elixirschool.com/ja/) 公式と同じくらい詳しいElixirのガイド
  - [Elixir School(英語)](https://elixirschool.com/en/)  日本語情報古い場合があるのでこちらも
  - [Elixir公式ドキュメント](https://hexdocs.pm/elixir/Kernel.html)
  - [Elixir入門 | gumi TECH Blog ](https://dev.to/gumi/elixir-01--2585)
- Phoenixの文法を知りたい
  - [Phoenix公式ドキュメント](https://hexdocs.pm/phoenix/overview.html)
- 最新の情報を知りたい
  - 全面的にElixirを採用しているgumiさんの[テックブログ](https://dev.to/gumi)
- 使うときのTipsを知りたい
  - fukuoka.exでは[Qiita記事](https://qiita.com/organizations/fukuokaex)を積極的に執筆しています
- そんなことはいいからとにかく動かしたい！
  - 全7回あるチュートリアル [Excelから関数型言語マスター1回目：データ行の”並べ替え”と”絞り込み”](https://qiita.com/piacere_ex/items/6714e1440e3f25fb46a1)
  - 手前味噌ですが頑張って書きました[【Phoenix1.4】（前編）パスワード認証＆リレーションあり「ブログチュートリアル」](https://qiita.com/koyo-miyamura/items/82f6735a911339bc6607)
- 質問したい
  - [elixirforum（英語）](https://elixirforum.com/)
  - Twitterで [#fukuokaex](https://twitter.com/search?q=%23fukuokaex&src=typd&lang=ja) のハッシュタグをつけると、fukuoka.exの代表[piacere](https://twitter.com/piacere_ex?lang=ja)さんを筆頭に答えてくれます．(piacereさんは尋常じゃなくディープな話ができるので、Elixirのここんとこどうなの！？という質問をしてみると面白いかもです笑