Elixir

【小ネタ】Eixirのパイプ演算子使用中に第一引数の値を第二引数に渡す方法

この記事はfukuoka.ex Elixir/Phoenix Advent Calendar 2018 23日目の記事です。

こんにちは!Elixir学習中、業務では主に手動のテストをやっているyoshitakeです。

今回はAdvent Calendarの記事として、Elixirを学んで勉強中に知った小技を紹介します。


Elixirのパイプ演算子

僕が参考にしている、 @piacere_ex さんのExcelから関数型言語マスター1回目:データ行の”並べ替え”と”絞り込み” - Qiitaにもサラッと書かれていますが、Elixirにはパイプ演算子というものがあります。

これは、|>でつなぐと、左側に記述した変数や関数の出力が、右側に書かれた関数の第一引数になる。

というものです。

簡単にパイプ演算子を使った例を紹介します。

def mul(a, b)do

a * b
end

def div(c, d)do
c / d
end

上記のように、2つの数値の掛け算・割り算を行う関数mul, divがそれぞれあったとします。

この関数を使って、 (5 × 4) / 10 を計算しその結果を表示する場合、パイプ演算子あり、なしではそれぞれ以下のようになります。

# パイプ演算子なし

IO.puts div(mul(5, 4), 10)

# パイプ演算子あり
mul(5,4)
|> div(10)
|> IO.puts

このパイプ演算子のおかげでデータの流れや変化がわかりやすい、というのが個人的な感想です。

直感的でわかりやすいなぁ…と思います。

しかし、このパイプ演算子は 次の関数の第一引数としてデータを渡すので、第一引数以外の引数にデータを渡す場合はちょっと工夫が必要とのことです。

そこでこの記事では、私が教えてもらった3通りのやり方を紹介します。


パイプ演算子で第一引数以外にデータを渡す方法

以下の3つの方法があるそうです。


  1. swapする関数を作る

  2. 匿名関数(無名関数)を使う

  3. 匿名関数(無名関数) + 省略記法(ショートハンド)を使う

先程の例 div(c,d)に対して c/dではなく、d/cをしたい、という処理について考えてみます。


1. swapする関数をつくる

def swap_div(c, d)

d / c
end

mul(5,4)
|> swap_div(10)
|> IO.puts

こんな感じです。

第一引数でもらうという事象は変更できないので、関数の中で順番を変更するですね。


2. 匿名関数(無名関数)を使う

mul(5, 4)

|> (fn n -> 10 /n end).()
|> IO.puts

Elixirには匿名関数(無名関数)をパイプ演算中に記述することができます。

それを記述し、その中で第一引数を他の処理に配置したコードを書いたらOKです。

■ 参考

関数 · Elixir School


3. 匿名関数(無名関数) + 省略記法を使う

mul(5, 4)

|> (&div(10, &1)).()
|> IO.puts

Elixirの匿名関数には省略記法があるそうで、省略記法を使うと第一引数を&1第二引数を&2という感じで使えるようになるそうです。

■ 参考

関数 · Elixir School


おわりに

さて、Elixir勉強中に習った小技を紹介しました。

これがなんの役に立ったのか?というと、Regex(正規表現)を使っているときに役立ちました。

Regexをパイプ中に使ってたのですが、データを第二引数に渡したい!と思ったんですよね。

それについてはまたの機会に。

では、ここまで読んでいただきありがとうございました!

※ 他にも方法ある場合教えていただけると嬉しいです。

よろしくお願いします。

■ 参考

Regex – Elixir v1.7.4