『プログラミング Elixir』を読んで

プログラミングElixir
プログラミングElixir
posted with amazlet at 16.08.22
Dave Thomas
オーム社
売り上げランキング: 1,168

川崎 Ruby 会議 01 の会場で、訳者の笹田さん・鳥井さんから一冊献本いただきました!ありがとうございます!さっそく読み終えたので、紹介を書いてみます。

書評

Elixir に興味がある人がこの本を読むべきなのは、言うまでもないと思います。そういう人は、Elixir に詳しそうな人による書評(このへんとかこのへんとか)を見るといいと思います。

正直、自分はさほど Elixir に興味ないのですが、この本はとてもおもしろく読むことができました。なぜかというと、Ruby っぽいオレオレ言語を作りたい野望を漠然と持ってる人間には、非常に刺激的な内容だったからです。Elixir 自身が「Erlang VM の上で Ruby っぽい言語を作ったらどうなるか」というのを体現していて、「あーわかるわかる、Ruby ここ良くないよね」とか「うわー Erlang VM のつらみを継承してるなー」とか思いながら読んでたら、一日で読み終えてました。

Elixir 自身だけでなく、本書の構成や説明がどことなく「Ruby ファンの、Ruby ファンによる、Ruby ファンのための」という感じだったのも面白かったです。Erlang/Elixir というと、とにかく並列性の話を期待しますが、本書の第 I 部(2〜13 章)では並列性の話は全く出てきません。150 ページ以上かけて、Elixir 言語自体をじっくり説明します。しかし、退屈にならないように構成と説明が工夫されています。まずはパターンマッチ(2 章)と不変性(3 章)という Ruby にはない性質から始めて、それから言語全体を概観する(4 章)。それから関数の話をし、リストとからめて再帰まで説明する(5〜7 章)。その勢いで他のコレクションや文字列などデータ構造の話を流し(8〜11 章)、ここでいまさら制御フロー(12 章)。斬新な流れでした。ここで終わると、この後いざ何か書こうとしたときに砂漠の真ん中に放り出されたような気分になりそうですが、最後の 13 章で、GitHub の issues をフェッチして整形出力するちょっとしたアプリを題材に Elixir での開発フローのデモがあり、フォローも万全でした。

そうして Elixir という言語を一通り理解した上で、第 II 部はついに並列性の話です。が、ここはさらっと流されている感じでした。プロセスやノードの低レベル API の話(14〜15 章)と、高レベル API というか OTP という並列実行管理システムの話(16〜18 章)などでした。この辺は明らかに、これだけで本が数冊書けるレベルのものなんだろうなーというところはよく分かりました(そして自分が興味ないところなので、ここを飛ばすのは「いいぞもっとやれ」という感じ)。最後の第 III 部は、マクロやモジュールに駆け足で触れて終わり。

ということで、第 I 部が個人的には一番エキサイティングでした。Elixir に興味がなくても Ruby とオレオレ言語設計に興味がある人(誰?)は是非読むといいと思います。

(なお、関数型プログラミングに関する記述については、ちょっと怪しい雰囲気がありました。sum の再帰的構造が sum([head|tail]) = <> + sum(tail) とか。アキュムレータの説明をしたかったようですが。まあ、「この本で関数型プログラミングを勉強しよう」と思う人はいないと思うので大丈夫かと思います)

Elixir について

さて、以下は書籍ではなく Elixir 自体への感想となります。

上述の通り、良くも悪くも「Erlang VM の上で Ruby っぽい言語を作ったらどうなるか」という感じの言語でした。Erlang といえば「VM は最強だけど言語は残念」ということで有名なので、かなり使い易くなっていると言えるのではないでしょうか。(使い込んだわけではないので印象ですが)

さらに、Ruby の弱点を克服しているところも好印象でした。Ruby 最大の不足である(と自分が思っている)パターンマッチは、Erlang 由来でばっちり用意されています。ブロックがキーワード引数の構文糖であることはすばらしいアイデアだと思いましたし、構文木をいじれるマクロは良し悪しですが、これらを組み合わせることで if 文相当が自力で定義できるのは非常にポイント高いです(Ruby がメソッド呼び出し 1 個あたりブロック 1 個しか書けないのは、if 文的なのを自分で定義できないのでしばしば苦痛です)。地味ですが、独自拡張可能な %-記法(Elixir では ~-記法)も「わかってるなー」という感じでした。

ただまあ、enjoy programming 勢としては、Elixir を普段使いにしたいとは思いませんでした。並列性ごときのために、あらゆる値が不変(配列やハッシュがない)のは、無理です*1。文字列・バイナリ周りのややこしげな仕様は、Erlang VM を利用する宿命かなんかですかね。それから、関数型プログラミングのは多分不変性と相性がいいからかと思うのですが、それにしても「メッセージを順次処理する」という単純なループを表現するのに末尾再帰を使うのは、やや滑稽に感じました。*2

それから、並列性がウリというわりには、それに特化した言語機能はないですよね。プロセス起動の spawn_link などには専用の記法があってもよさそうな。また、並列プログラミングのヤバさ(デバッグやテストがしにくい)を軽減してくれるような言語機能もなさげなので、ちょっと期待外れ感もありました。Erlang 的にはこのへんは言語機能ではなく、OTP という超重厚システムが頑張ってくれるというスタンスなんでしょうが、どうせ新たに言語を作るなら、OTP で培われたノウハウを言語機能として取り込めばよかったのになー、と思いました。OTP をほとんど理解してない人間の印象ですが。

ということで、Erlang VM の利点も欠点も継承してるなーという感じの言語でした。表層言語は Erlang から大分幸せになってるようですが(そしてそれはかなり重要ですが)、やっぱりこれは本質的に Erlang なんだと思います。

出来合いの VM の上で言語を作ると、どうしてもこういう妥協の産物になるんですよね。かといってスクラッチから書くと完成しないんですが。という感じで、オレオレ言語を作りたい野望を刺激される本でした。ああ。

*1:その犠牲を払ってでも並列性を必要としている人がいるのはわかってますし、そういう人にはいいんだと思います。でも自分にはつらい。

*2:普通は OTP の handle_call とかを実装するだけで、実際にはループを実装することがほとんどない言語なのかもしれません。