これは ドリコム Advent Calendar 2021 の17日目です。
16日目は さくらい さんの 自宅以外でリモートワークしてみた!~実家編~ です。
ドリコムでは、コロナ禍から現在もリモート勤務がメインとなっております。
社員それぞれがいろんなリモート知見を持っていると思いますので、その一端が見れて楽しいですね。

はじめに

こんにちは、enza部でSREっぽいことをやっていたりするハヤブサです。
皆さん、Elixirは好きですか! 私は好きです!!
闇の錬金術とはなんなのでしょうか?
私にもわかりません。この記事ではElixirについて話をして行こうかと思います。

Elixirについて

Elixir を知らない人に Elixir を説明している記事はたくさんありますが、スケーラビリティがよくて、軽量の実行スレッドがメッセージを通して情報をやり取りするので、多くのプロセスを立ち上げていくことで拡張できるっというのがあります。 ですがプロセス数を増やしてメッセージパッシングでそこそこのデータをやり取りすると性能劣化する可能性は高いですし、不意な問題が発生することもあるかと思います。 また Elixir はフォールトトレランスがよく対障害性が高いという触れ込みでもあります。 ですが死ぬときは死にますし、そのままお亡くなりになることもあります。ちゃんと対応しないと阿鼻叫喚になります。 ネガキャンでしょうか。いえ、他のどんな言語と同じといえば同じですが、しっかりとした設計と検証を行なっていれば応えてくれる言語です。

iex を使わずにインタラクティブに Elixir を使用できるか?

皆さんは対話型インターフェースは使われていますか?
Elixir にも iex という対話型のインターフェースが用意されております。
Elixir がインストールされている環境では iex とコマンドを実行していただければ対話的にElixir を使用することができます。 しかしここで iex コマンドを使用せずとも対話型インターフェースを開くことはできるのでしょうか? それができるのです。下記のようにコマンドを実行してみましょう。
% elixir +iex
Erlang/OTP XX [erts-XX.X.X]  [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Eshell VXX.X.X  (abort with ^G)
1>
なんと! 驚きです。
Erlang の対話型インターフェースである Eshell が起動するではないですか。
これはなんでなんでしょうか?

iex を雑に分解してみる

上記の動きをする理由を知るためには、まずは iex の動きを分解していくと理解しやすいと思います。 そうは言っても iex の中身の挙動を詳しく見ていくのは骨が折れるし Advent Calendar は他にもあるんだから、この記事だけで体力使いきれないよっと皆様思われているのではないでしょうか。 そこで Elixir のコマンドの実行をDryRunしてくれるオプションである ELIXIR_CLI_DRY_RUN オプションを使って iex が最終的にはどのような形になっているのかをまずは見てみましょう。
% ELIXIR_CLI_DRY_RUN='DryRunして欲しいと祈りを捧げる' iex
erl -pa 【Erlangの形式にビルドされたElixirのコード群】 -elixir ansi_enabled true -noshell -user Elixir.IEx.CLI -extra --no-halt +iex
DryRun してみますと、ご覧の通り、iex では最終的に erl に Elixir のソースコードを Erlang へとビルドしたビルド群と、各種オプションを引き渡している形となっています。
そして最後に件の +iex のオプションが渡されています。

+iex オプションなんて知らないぞ!

さてさて +iex というオプションですが、これはなんなのでしょうか。
iex とは Elixir の対話型インターフェースですので Erlang 側にオプションがあるとは考えにくいです。
また Elixir のドキュメントなどにも記載がないため謎のオプションだと皆様考えられているのではないでしょうか。
※ Erlang 側の内容を全部見たわけでもなく Elixir 側のドキュメントも全て網羅しているわけではないので上記の記載には間違いがあるかもしれません +iex に関しては elixir コマンドの中に記載があります!
elixir コマンドに関しては、ただのシェルスクリプト です。
なので素敵なテキストエディタで開いてみることができます。
該当の箇所は下記となります。
while [ $I -le $LENGTH ]; do
  S=1
  case "$1" in
    +iex)
        set -- "$@" "$1"
        MODE="iex"
        ;;
    +elixirc)
        set -- "$@" "$1"
        MODE="elixirc"
        ;;
    -v|--no-halt)
        set -- "$@" "$1"
        ;;
    -e|-r|-pr|-pa|-pz|--app|--eval|--remsh|--dot-iex)
        S=2
        set -- "$@" "$1" "$2"
        ;;
上記は elixir コマンドにオプションとして引き渡された内容をチェックする箇所ですが
なんと+iex と +elixirc というオプションが存在しております。 これは隠しオプションとして設定されており Mode として Erlang 側に引き渡すときの切り分けの方法として存在しているようです。
下記は iex コマンドの一番最後の行
となりますが、こちらの実装内容を確認することで上記へと続いていることもわかりやすいのではないでしょうか。
exec "$SCRIPT_PATH"/elixir --no-halt --erl "-noshell -user Elixir.IEx.CLI" +iex "$@"
iex のコマンドも最終的には elixir コマンドへと引き渡され、そして elixir コマンドからは Erlang 側へと引き渡されている。
Elixir が Erlang で動いているのが少し身近に感じられたのではないでしょうか。

それでどうした

今回の記事は Elixir の開発で明日から全く役に立たない知識の解説となります。
Advent Calendar という年に一度のお祭り企画ですので、普通なら気にもしない闇の錬金術に触れていただき、楽しんでいただけたのなら嬉しいです。 また Advent Calendar が終わった後、 12月26日には Tokyo.ex14 が開催されます。
上記のような Elixir の深淵から初心者向けのセッションまで自由な形で行なっておりますので興味のある方はオンラインで開催していますので参加してみてください。 ドリコムでは一緒に働くメンバーを募集しています!
募集一覧はコチラを御覧ください!