はじめに
2週間ほど Elixir を触ってみて感じた魅力について語ってみます。
他にパフォーマンス面の魅力も多々あるのですが、まだ踏み込めていないので表面的な部分にとどまってます。
パイプライン演算子
d(c(b(a(1234))))
他の言語でこのようなコードを見かけることは多いのではないでしょうか。
見慣れてはいますが、処理の順番が「内→外」となっており、わかりづらいです。
1234 |> a() |> b() |> c() |> d()
Elixir ならこう書けます。
順番が「左→右」になりわかりやすくなりましたね。
Elixir では標準ライブラリの多くがパイプライン演算子を使いやすいように設計されています。
私にとっては新鮮でしたが、 bash に精通している方はイメージしやすいのでしょうか?(私はあまり詳しくありません)
全ての値渡しがパターンマッチ
{a, b} = {1, 2}
Elixir ではこういったコードが書けます。
ですが、ここまでだと Ruby などの言語にも似たような構文がありますね。
Elixir では他の値渡し、つまり関数の呼び出しでも全く同じことができます。
2次元上の2点間の距離をもとめるコードを書いてみます。
defmodule F do
def distance({x1, y1}, {x2, y2}) do
:math.sqrt(:math.pow(x1 - x2, 2) + :math.pow(y1 - y2, 2))
end
end
受け取った引数をいちいちバラバラに代入しなおしたりする必要がありませんね。
ここでは紹介しませんが、上記の Tuple の他に List や Map でも同じことができます。
動的なオーバーロード
一般的なオーバーロードと言えば、「引数のシグネチャによって呼び出す関数が変わる」といった仕組みです。
動的型言語である Elixir にオーバーロードはできないのでは?と思うかもしれませんが、できます。
ユークリッドの互除法で最大公約数を求めるコードを書いてみます。
defmodule F do
def gcd(a, 0), do: a
def gcd(a, b) when a < b, do: gcd(b, a)
def gcd(a, b), do: gcd(b, rem(a, b))
end
アルゴリズムについては Wikipedia あたりを参照していただければと思います。
おもしろいのは、一般的なオーバーロードと違い、実行時に呼び出す関数が決められるという点です。
動的型言語ならではの魅力と言えます。
when
という節がありますが、これはガードと呼ばれます。
関数を呼び出すかを決める if
のようなもの、と考えていただければ間違いないです。
おわりに
Elixir の魅力を紹介させていただきました。
どうでしょう、素晴らしくないですか?
拙い記事ながら、誰かが Elixir に触れるきっかけになれば幸いです。