この記事は「Elixir Advent Calendar 2023」14日目の記事です
東京にいるけどfukuokaexのYOSUKEです。
普段は 合同会社TheWaggle で教材開発・システム開発・研修講師などマルチに活動してます。
このシリーズでは、文系ですらない、体育会系でも始められるプログラミング学習 というテーマで元自衛官だった僕が
自衛官からエンジニアになってもらいたいという気持ちを込めて、普段は大人しいですが、このコラムシリーズでは、あえて、体育会系のノリで、貴様ら理屈で覚えるなら体で覚えろ!というノリで書いてみたいと思います。
なので、初学者向けですが、理論は後回し、まずは動かして体感しろってノリの第14回目です。
それでは、いくぞ!
パイプ演算子による関数の連鎖
よーし、貴様ら今回は前回の続きだ、
Enum.map([{1,2}, {3,4}], &Tuple.to_list(&1))
[[1,2],[3,4]]
Enum.mapの2番目の要素にはfun
を入れるとあって、それは関数
のことだと言ったな、そして、それであればTuple.to_list()
も使えると教えたはずだ。
ただし、よーく見ると&Tuple.to_list(&1)
とあって、この&
はキャプチャ演算子
と行って、&
を置いた右側を関数化
してくれる便利な道具だという話しをした。&1
は関数を使う時に値を入れる入り口になる役割をになっている。この関数に値を渡す入り口の事を引数
という。
そして、&
は、ちょっとした仕事をさせたい時、変数
に入れて使う事ができる。というのが前回教えた事のまとめだ。例えば、田中に仕事をさせる様を変数tanaka
とした場合、数値を渡したら2倍にする仕事を頼む様子を以下のように表現できる。
tanaka = & &1*2
tanaka.(2)
4
また、前回は鈴木に数字を渡したら、-1する仕事も頼んだ
suzuki = & &1-1
suzuki.(2)
1
ここまでが前回にやった事だ、そして、今日は貴様らに頼んだ仕事を連携するやり方を教えてやろう。
例えば、tanakaに頼んだ仕事をしたのち、鈴木に仕事を頼み、渡した数字を2倍したあと、-1する事をお願いした場合だ。
suzuki.(tanaka.(2))
3
さて、このように引数
に直接、tanakaを入れても良いのだが、これだと順番がわかりづらいな。間違えて逆にしてしまうと結果がまるで変わってしまう。
tanaka.(suzuki.(2))
2
このように本来、3という結果を期待してるのに、順番が変わるだけで違う結果が返ってきてしまう。
この呼び方は少々、順番がわかりづらい!
そこで、貴様らでも命令の順番がわかりやすいように今日は、関数
に仕事をさせる上で命令の呼び出し順をわかりやすくする書き方を教えてやろう!
そこで使うのが|>
これだパイプ演算子
という。こいつを使って、tanakaとsuzukiの命令順が明確になる。
tanaka.(2) |> suzuki.()
3
これは、tanakaに先に仕事をさせ、2を渡して2倍にする、そしてその後にsuzukiにtanakaが仕事をした結果の値をそのまま渡して使えという事でsuzuki.()
の()
の中は空のままでいい事になっている。
もし、suzukiに2つの引数を入れるような仕事を与えた場合はどうなるかも見せてやろう。
suzuki = & &1 - &2
suzuki.(2,1)
1
このように最初の引数の値を2つ目の引数で引く仕事とした場合だ。この場合、tanakaとの連携は以下のように命令すれば良い。
tanaka.(2) |> suzuki.(1)
3
このように、一つ目の引数は、tanakaから渡ってくるから、2つ目の引数の数値をsuzukiに渡せば良い。
何?頭がこんがらがってきただと!
貴様らのような奴は自分で必ず体験しろと言っただろう!何をボーッと説明を聞いてるんだ。
自分たちでも手を動かして、色々と数字を入れたりさせたい仕事を変えてみたりして試すんだ!
何? 実際にやったら変なのが出るだと?
tanaka = & &1*2
#Function<42.125776118/1 in :erl_eval.expr/6>
#Function<42.125776118/1 in :erl_eval.expr/6>
これは、田中、貴様には認識番号があるな?
もし、戦場で死亡しても認識番号が書いてあるタグを仲間が持って帰れば貴様が戦場で倒れた事が明確になる。
#Function<42.125776118/1 in :erl_eval.expr/6>
これは、貴様にこの仕事を頼んだことが明確になるようにプログラム側が認識するための認識番号のようなものだ。今のところ、貴様らがあまり気にする必要はない!
気にせず、試せ!わかったな。
よし、ではいよいよ、この仕事&Tuple.to_list(&1)
を|>
を使ってわかりやすく紐 とくとこうなる。
& &1 |> Tuple.to_list()
では、実際に動かしてみよう。
Enum.map([{1,2}, {3,4}], & &1 |> Tuple.to_list())
[[1, 2], [3, 4]]
そして、 & &1
は何をしてるか、さらに次の命令をtakahashiにやってもらおう。
takahashi = & &1
takahashi.(1)
1
これは、&
関数化する道具だが、右側には特に何もなく、&1
で入り口を作ってるだけ。よって、値をそのまま引き渡す役割を担っているわけだ。
要するに、あらかじめ用意されている関数に値を引き渡す役割を&Tuple.to_list(&1)
このような命令書いてたわけだ。
つまり、& &1 |> Tuple.to_list()
関数にただただ、値を引き渡しているだけってことだな。
よし、今日はここまで、それでは次回 Part15でまた会おう!