Rubyistはしばしば Rubyをキメると気持ちがいい
という言葉を使います。
私もRubyが好きなのですが同じか、近頃はElixirをキメるともっと気持ちがいいと感じます。
マイナーな、仕事も少ない言語なのになぜか?
ポエムです。ですが自分がこんなに素晴らしい言語を触っているという事実を認めたかったこと、そして知らない人がElixirに興味を持つきっかけとなったら嬉しいのでまとめます。
Why Elixir?
僕が思うElixirの好きなところは以下の通り。
多分もっとあるはずですからこれが好き!みたいなのがあれば教えてほしいです
-
|>
で処理を繋げられるのが気持ちいい - 再帰を書きやすいのが気持ちいい
- ASTを書けるのが気持ちいい
- 新雪を踏む感触が気持ちいい
です。
順番に書きますねぇ?
|>
で処理を繋げられるのが気持ちいい
プログラミングElixirには「プログラミングは値をどんどん変換して行くことだ」と書かれていました。
プログラマとして働く中でプログラミングとはなにか?という問いに一つの答えを与えてくれた一文で私にとっては一つの転換点となった言葉です。
Elixirでは与えられた値を |>
を用いて別の値に変換していきます。
ちょっと例を見てみましょう。
def count_each_word_size(str) do
str
|> String.split(" ")
|> Enum.map(fn (word) ->
length(word)
end)
end
↑の例では引数 str
を |>
の右側に書かれている関数に渡して値を変換していきます。
次の行の |>
では上の行の戻り値が(第一)引数として与えられます。
|>
があることでデータが段々と変わるさまを簡単に表現できます。
一切変数を使うことなく引数を期待する値に変換したときの気持ちよさは他の言語では味わえない快感なのでまだの人は是非キメていただきたい。
再帰を書きやすいのが気持ちいい
「ループは人の技、再帰は神の技」という言葉を聞いたことがあります。
Elixirにもfor文もありますが私はほとんど使うことはありません。なぜなら再帰を書きたいからです。
どこにでもある再帰の書き方としては以下のような感じかな?
def sum(list)
return 0 if list.empty?
head = list.first
tail = list.drop(1)
head + sum(tail)
end
# 実用性は...ないです。
再帰のお約束は関数の最初の方に終了条件を書くこと。これがないと無限ループしちゃう。
その後に実際にやりたい処理を書く。
他の言語ではどうしても一個の関数に終了条件と期待する処理を書くことになる。
ただしElixirだとこれをきれいに解決できる。
上のコードならこんな感じになる。
def sum([]) do
0
end
def sum([head|tail]) do
head + sum(tail)
end
↑のような書き方ができる。
他の言語に慣れていると気持ち悪いと思うかもしれませんね。でも大丈夫。すぐに良さに気づきますから。
ご覧の通りElixirでは同じ名前の関数を引数違いで複数実装できます。
例の場合は引数が空配列の場合と値がある場合で書いてます。
さらに配列は [head|tail]
と書くことで head
に配列の先頭が、 tail
に先頭以外の値が勝手に代入(Elixir的には束縛という)されます。なので複雑になりがちな再帰関数を完結に記述できるんですねぇ。
再帰をキメるとそれはもう気持ちいいことこのうえないですよ!
ASTを直接書けるのが気持ちいい
AST、抽象構文木ですね。
多くのプログラミング言語では eval
という関数が存在すると思います。文字列を評価してくれる関数ですね。
Elixirの場合はこのEvalが解釈する部分をElixirで実装することができます。
これができると何ができるか?ということですが、オレオレif文とかオレオレfor文とか書けたりします。
重要なのは quote
(評価する部分)と unquote
(意図的に評価しない部分)です。
Elixirスクールからオレオレunlessを実装した素晴らしい例をお借りします
defmacro unless(expr, do: block) do
quote do
if !unquote(expr), do: unquote(block)
end
end
基本的には quote do ~ end
の中に書きますが後で処理したいところだけは unquote
しておきます。
こうすることで unless
に渡された do ~ end
部分はunlessが評価された後に実行されます。
ただのevalではこの芸当はなかなか難しいはずです。
このマクロ機能は他の言語のマクロとは一線を画しLISPより受け継がれてきた古の秘技をキメられます。
新雪を踏む感触が気持ちいい
Elixirは比較的新し目の言語で2012年から歴史に登場します。
言語の洗練さに対して歴史は浅く(Go言語などと比べれば)かゆいところに手が届くと言えるほどエコシステムは整っていません。
逆説的に言えば、プログラマが新雪を踏める多くの機会があるということでもあります。
誰にも触れられていないそれを自分たちで踏みしめ切り開く感覚はすでに多くが開拓された他の言語ではなかなか味わいにくいところがあると思います。
ここで一つElixirに飛び込んでコントリビュートしてみるのも楽しいかもしれません。
おきもち
以前Elixirのドキュメントの修正で小さいPRを投げたことがあるのですが、joseさん(Elixirの作者)はすぐにマージしてくれたりとコミュニティはとても開かれていると思います。
決して情報が多い言語ではありませんが、Phoenix(RubyでいうRails的なWebフレームワーク)やmix(RubyのRakeとbundlerの合体版みたいなCLI)など本当に必要なところはしっかり固められています。
またErlangVMで動くためErlangの資産へのアクセスも可能でGoやRubyほどなんでも揃うことは無いですが何もない言語ではありません。
これからの発展のためになにかできることがあればなぁと思いつつElixirを書いて楽しんでます。