初めに(ポエム)
Elixir は関数を呼び出す際の括弧を省略できます。
無名関数はキャプチャ演算子で略記ができます。
これら複合技により、スマートに早くコーディングできるのですが、初学者にはとても分かりにくい・・・。
初学者、初見殺しです。
諦めないためにも、ここで色んなパターンを見て、理解を深めて貰えたらと思います。
「括弧の省略」「無名関数」「キャプチャ演算子」の組み合わせを理解する
まずは、基本的な部分についておさらいします。
無名関数
無名関数の作成はfnで始まりendで終わります。
例:fn (x, y) -> x + y end
->の左側には仮引数(parameters)の組(x, y)
がカンマで区切られています。
仮引数は、呼び出された関数などが値を受け取るために宣言された変数のことです。
関数作る時に、最初に関数名と受け取る引数を書きますね。その引数を仮引数と言います。
->の右側に書かれた式x + y
が無名関数の本体です。
無名関数をadd_fn
に束縛した場合、add_fn.(引数1,引数2)
で引数を与えて呼び出せます。無名関数の時はドットが必要なので忘れないように注意ください。
(逆に名前付き関数では、ドットが不要です。)
iex> add_fn = fn (x, y) -> x + y end
#Function<41.3316493/2 in :erl_eval.expr/6>
iex> add_fn.(1,5)
6
fn (x, y)
の括弧は省略することができます。
iex> add_fn = fn x, y -> x + y end
#Function<41.3316493/2 in :erl_eval.expr/6>
iex> add_fn.(1,5)
6
キャプチャ演算子
キャプチャ演算子を使って、fn -> end
までのくくりを&()
、
x, y -> x + y
の第一引数x
を&1
として、第二引数y
を&2
として簡略化することができます。
先ほどの関数をキャプチャ演算子で置き換えてみましょう。
iex> add_fn = &(&1 + &2)
&:erlang.+/2
iex> add_fn.(1,5)
6
とてもシンプルです。分かりにくいと思うかもしれませんが慣れです。
基本、fn x, y -> x + y end
の書き方の方が煩わしいので使わないです。
ここからが分かりにくなるので、自分でプログラム打ちながら確認してください。
括弧は省略できます。ただし、最初の&
の後に空白を入れないとコンパイルエラーになります。
iex> add_fn = & &1 + &2
&:erlang.+/2
iex> add_fn.(1,5)
6
しかし、&
の後に関数が続く場合、空白は不要です。
以下の例では、出力結果をIntegerからStringに変換しています。
iex> add_fn = &to_string(&1 + &2)
#Function<41.3316493/2 in :erl_eval.expr/6>
iex> add_fn.(1,5)
"6"
後ろの括弧も省略できます。
iex(14)> add_fn = &to_string &1 + &2
#Function<41.3316493/2 in :erl_eval.expr/6>
iex(15)> add_fn.(1,5)
"6"
正直、初学者からすると&to_string
で一つの関数に見えるし、
後の処理でも&1 + &2
が付いているので、&
いっぱい付いててなんだろこれ?になります。
もっと省くこともできて、空白も省けます。
iex(18)> add_fn = &to_string&1+&2
#Function<41.3316493/2 in :erl_eval.expr/6>
iex(19)> add_fn.(1,5)
"6"
初学者の初見殺しです。
コンパイルエラーにはなりませんが、可読性が悪いので、普通はここまでしないと思います。
実際には、以下のようなパターンで表記される事が多いと思います。
iex(22)> add_fn = &(to_string &1 + &2)
#Function<41.3316493/2 in :erl_eval.expr/6>
iex(23)> add_fn.(1,5)
"6"
また、キャプチャ演算子を用いることで関数を無名関数と同じように呼び出せるので、
以下のようにも書けます。
そろそろパターン多くて飽きてきますが、たくさん見慣れておいてください。
to_string/1
の/1
は、アリティ(引数)が1個という事です。
こちらは、割り算の演算子/
と同じなので、一瞬割り算かと思いますが、関数の後に付いているのでアリティだと読み解いてください。
iex> add_fn = &to_string/1
#Function<42.3316493/1 in :erl_eval.expr/6>
iex> add_fn.(1 + 5)
"6"
どうやって見分けるのか?
&
が一つだけ出てきたら、無名関数だと認識しましょう。
&&
で論理積の演算子になりますが、あまり出てこないと思います。
さいごに
Elixirのソース見て、&
たくさん付いてて意味不明と、嘆いている初学者の方の一助になればと思います。
誤りなどありましたらご指摘お願いいたします。