💡
Elixirの無名関数④:パターンマッチング -- YouTube チャンネル daimon.ex 第8回解説
動画
Elixir の 無名関数③:&記法の続きです。
パターンマッチングを利用して無名関数を作る
今回の動画のライブコーディング冒頭で次のような演習問題が提示されました:
【演習問題】次のような仕様の無名関数を作りなさい。
- 2個の文字列を引数として取る。
- 2つの引数が両方とも空文字のときは、空文字列を返す。
- 2つの引数のうち一方が空文字列のときは、他方をそのまま返す。
- 2つの引数が両方とも空文字でないときは、2つの引数を空白文字1個で連結して返す。
これの意味するところを具体例で示すと次のようになります:
-
""
と""
が与えられたら""
を返す。 -
"ab"
と""
が与えられたら"ab"
を返す。 -
""
と"cd"
が与えられたら"cd"
を返す。 -
"ab"
と"cd"
が与えられたら"ab cd"
を返す。
パターンマッチングを使わずに作った例がこれです:
fn a, b ->
if a == "" do
b
else
if b == "" do
a
else
a <> " " <> b
end
end
end
パターンマッチングを使って書き直した例がこちらです:
fn
a, "" -> a
"", b -> b
a, b -> a <> " " <> b
end
caseマクロとの比較
パターンマッチングを利用して作られた無名関数は case マクロと似ています。次の例をご覧ください:
case {a, b} do
{a, ""} -> a
{"", b} -> b
{a, b} -> a <> " " <> b
end
タプル {a, b}
が与えられ、a
と b
にそれぞれ文字列がセットされているとき、上記の式を評価すると前述の無名関数と同じ結果が得られます。
ただし、case
マクロの場合、次のような書き方はできません:
case a, b do
a, "" -> a
"", b -> b
a, b -> a <> " " <> b
end
このコードはコンパイルエラー(undefined function case/3
)を引き起こします。
名前付き関数におけるパターンマッチング
動画の中で作成した無名関数を再掲します:
fn
a, "" -> a
"", b -> b
a, b -> a <> " " <> b
end
これを名前付き関数に変換するとどうなるでしょうか。case
マクロを使って次のように書き換えるのは一案です:
def concat(a, b) do
case {a, b} do
{a, ""} -> a
{"", b} -> b
{a, b} -> a <> " " <> b
end
end
しかし、もっとElixirらしい書き方があります:
def concat(a, ""), do: a
def concat("", b), do: b
def concat(a, b), do: a <> " " <> b
Discussion