Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

ラウンドテーブル 20190607 ~ Elixir入門 ~

目次

  • |> Elixir って何?
  • |> GoとElixirのコードを比較してみる
  • |> 「Erlang & Elixir fest 2019」 レポート
  • |> Elixir ハンズオン!
  • |> まとめ
  • |> もっと学びたい人へ

Elixirって何?

Elixirのwikiより

Elixir (エリクサー) は並行処理の機能や関数型といった特徴を持つ、Erlangの仮想マシン (BEAM) 上で動作するコンピュータプログラミング言語である。ElixirはErlangで実装されているため、分散システム、耐障害性、ソフトリアルタイムシステム等の機能を使用することができるが、拡張機能として、マクロを使ったメタプログラミング、そしてポリモーフィズムなどのプログラミング・パラダイムもプロトコルを介して実装されている

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

Erlangのwikiより

Erlang(アーラン)は、コンピュータにおいて汎用的な用途に使うことができる並行処理指向のプログラミング言語および実行環境

Erlangはエリクソンにより次の条件のシステムを構築できるよう設計された。

  • 分散化された環境
  • 障害に耐性をもつ (フォルトトレラント)
  • ある程度のリアルタイム性を備える
  • 無停止で稼働する

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

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

さらにElixirには以下の強力なフレームワークがあります

  • Railsの開発メンバーによって開発された、RailsライクなWebフレームワーク 「Phoenix」
  • 近年台頭してきた組み込み/IoT向けのフレームワーク「Nerves」

また、私が所属しているfukuoka.exではElixirの特徴を以下のように述べています

一般的に「関数型言語」と言えば、言語の習得が難しく、組織として選定しづらいイメージがありますが、Elixirは、言語仕様や構文がシンプルかつ簡単なので、「育成や習得の容易性」を切り捨てること無く、関数型のメリットも享受できます

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

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

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

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

ちなみに私はElixirのコミュニティ「fukuoka.ex」にて高速フーリエ変換(FFT)のライブラリ書いたり、Qiita記事書いたりしています

※実はカヤックのテックブログにもめっちゃ詳しい記事があります笑

GoとElixirのコードを比較してみる

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

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

Go

package product

func product(a, b int) string {
	if product := a * b; product%2 == 0 {
		return "Even"
	}
	return "Odd"
}
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

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
defmodule AtcoderPracticeTest do
  use ExUnit.Case
  doctest AtcoderPractice
end

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

ちなみに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

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

Elixir

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

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


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

Erlang & Elixir fest 2019 レポート

6/1に開催された「Erlang & Elixir fest 2019」に行ってきました!

ロマサガRS における Elixir サーバー開発実践 ~生産性を上げてゲームの面白さに注力~

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

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

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

XFLAG × スポーツ × Elixir

mixiさんによる Elixir のプロダクション導入事例

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

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

その他

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

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

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


日本ではアカツキやgumiやmixiなどでElixirが使われています

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

Elixir Conf Japan 2017 レポート | gumi TECH Blog

そしてこの日、会場が最もどよめいたのが、幾田が「gumiは、Erlang + pythonの会社からElixirへ移行し、Erlangによる既存資産(※弊社のソーシャルゲーム開発における共通基盤)を全部Elixirにリプレイスします。今後、Erlangによる新規の開発をやめます!」と発表した瞬間。弊社のCTOとしての突然の決意表明に、会場からは驚きの声があがりました

ちなみに世界に目を向けると実は「Discord」でも使われていたり!

Elixir ハンズオン!

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

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

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

まとめ

私がこの1年でElixirを触ったりウォッチしてみた所感は以下です(個人の感想)

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

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

もっとElixir学びたい人へ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment