[翻訳] Elixirのパターンマッチング

Trace Helmsさんの2015年10月28日付のブログ記事[Pattern Matching In Elixir](https://quickleft.com/blog/pattern-matching-elixir/)の翻訳です。
Elixirではパターンマッチをうまく使うと条件判断などを使わないでプログラムが見通しよく綺麗に書けます。Idiomも多数あるようです。
入門記事としてよくまとまっていたので復習の意味も兼ねて翻訳してみました。

-----

# まえがき

新しい言語を学ぶことはプログラミングについての知識を広げるよい方法です。いくつかのかっこいい技や物事の新しい考え方を身に付けることができるでしょう。私が学んだ中でElixirが他とちょっと違うのは[パターンマッチング](http://elixir-lang.org/getting-started/pattern-matching.html)でした。それはElixirのルーツであるErlangから来ており、私はこういう機能が他の言語でも使えたらなあとずっと思っているものです。

# パターンマッチングとは何か

Elixirでは`=`という記号は必ずしも「この変数の値を他の値と等しく設定する」という意味ではありません。その代わり「左辺を右辺とマッチさせる」という意味を持ちます。普通`x = 2`のように宣言できるのでその違いには気づかないでしょうが、遅かれ早かれちょっとこれは違うな？と気づくことになるでしょう。

```iex
iex> x = 2
2
iex> y = 3
3
iex> 2 = x
2 # なんじゃこりゃ?
iex> 2 = y
** (MatchError) no match of right hand side value: 3
```

あれれ、`2`は`x`という値と等しく設定されてないですよね。`2`は`x`とパターンマッチされただけだったんです。この違いは現時点では大した違いに見えないでしょうが、いろいろと使いみちがあるんですよ。説明を続けさせてください。

### イミュータブルな変数についての注記

Elixirは関数型言語であり、つまり変数はその値を変更されることがありません。しかし変数名は再利用できます。もし`x =2`と設定して次に`x = 3`と設定してもElixirでは問題ありません。

```iex
iex> x = 2
2
iex> y = 3
3
iex> x = y
3
iex> x
3
iex> ^x = 2 # ピン演算子で強制的に変数の再利用をしないようにした
** (MatchError) no match of right hand side value: 2
```

この状況の裏で、まだ変数`x`で値が`2`のままのものが残っています。例えば、並行動作する他の関数に変数`x`を渡した後に`x`を変更しても変更動作しているその関数は元の`x`の値を持ったままです。`^`[^1] を使うと強制的に変数の再利用をしないようにできますが、`^x = 3`は`x`がまさに値`3`を持っているのでマッチします。
[^1]: pin operator(ピン演算子)

# パターンマッチングの基礎

タプルがあったとして、その異なる値を幾つかの変数に割り当てたいとします。

```iex
iex> {result, value} = {:ok, 2}
{:ok, 2}
iex> result
:ok
iex> value
2
```

いいですねー。異なる値を取り出し変数に割り当てられました。ではここで結果が`:ok`の時だけ`value`に値を割り当てたいときは？

```iex
iex> {:ok, value} = {:ok, 2}
{:ok, 2} # this passed the pattern match
iex> value
2
iex> {:ok, value} = {:nope, 2}
** (MatchError) no match of right hand side value: {:nope, 2}
```

左辺の`:ok`が右辺と実際にマッチされています。`value`はタプル全体(`:ok`を含む)がマッチしたので値が割り当てられただけにすぎません。
2番めの式は`:ok`が`:nope`と異なる値のためマッチしません。またまたこれでは全然役に立たないみたいですが実際のコードでどのように使うか見てみましょう。[^2]

[^2]: 念のため、_は「どんなものともマッチする」変数です。ワイルドカードってElixirでは正式名称でしたっけ？(Scalaだとワイルドカードで通じる)

```ex
# my_case.exs
defmodule MyCase do

  def do_something(tuple) do
    case tuple do
      {:ok, value} ->
        "The status was :ok!"
      {:nope, value} ->
        "Nope nope nope nope..."
      _ ->
        "You passed in something else."
    end
  end

end
```

ではこれを`$ iex my_case.exs`で`iex`にロードしてみます。

```iex
iex> MyCase.do_something({:ok, true})
"The status was :ok!"
iex> MyCase.do_something({:nope, true})
"Nope nope nope nope..."
iex> MyCase.do_something({:wat, true})
"You passed in something else."
```

これでパターンマッチングがElixirでは便利な道具であるとおわかりいただけるようになってくれればいいのですが。パターンマッチングを適切に使えばコードを読みやすくすることできます。

# 関数定義におけるパターンマッチング

ここがパターンマッチングを使うと本当に光るところで、その後もずっとパターンマッチングを使う気になると思います。引数がパターンとマッチした場合のみ実行される関数を定義できます。

```ex
# talker.exs
defmodule Talker

  def say_hello(:bob), do: "Hello, Bob!"
  def say_hello(:jane), do: "Hi there, Jane!"
  def say_hello(name) do # name is a variable that gets assigned
    "Whatever, #{name}."
  end

end
```

ではこれを`$ iex talker.exs`で`iex`にロードしてみます。

```iex
iex> Talker.say_hello(:jane)
"Hi there, Jane!"
iex> Talker.say_hello(:bob)
"Hello, Bob!"
iex> Talker.say_hello("Trace")
"Whatever, Trace."
```

ご覧のとおり、3つの異なるメソッドが渡されたものによって呼び分けられていることがわかります。これがもっとすごいことができるための基礎となっています。例えばElixirでの再帰ですが、パターンマッチングに大いに依存しています。見てみましょう。

# 再帰での利用

リスト内の全ての変数を再帰的に2乗する関数を定義します。基本のケースとして空のリスト`[]`を渡した場合の定義から始めます。そしてその後実際に2乗する関数を定義しましょう。

```ex
# my_squarer.exs
defmodule MySquarer do

  def square([]), do: []
  def square([head | tail]) do
    [head * head | square(tail) ]
  end

end
```

Elixirではリストを最初の要素(head)とそれ以降のリストの残りと表現することができます。最後の要素は常に空のリストです。ですので`[head|tail]`と書けば文字通り最初の要素を`head`に、残りを`tail`にマッチさせることができます。

```iex
# example showing what head and tail are
iex> [head | tail] = [1, 2, 3, 4]
[1, 2, 3, 4]
iex> head
1
iex> tail
[2, 3, 4]
iex> [head | tail] = [1]
[1]
iex> head
1
iex> tail
[]
```

では我らの`square/1`[^3]関数に戻りましょう。この関数は`head`の2乗を先頭要素として持つ新しいリストを返し、残りの要素を埋めるべく`square/1`を再帰的に呼び出します。最後の要素に到達した後は`square([])`で定義された関数が空のリストとマッチして空のリストを返します。その時点で関数呼び出しの連鎖は終了して結果が返されます。
[^3]: `square/1`という書き方はElixir/Erlangの表現方法で「引数がひとつ(=アリティが1)なsquareという関数」を意味します。

では動作を見てみましょう。$ iex my_squarer.exs`で`iex`にロードしてみます。

```ex
iex> MySquarer.square([])
[]
iex> MySquarer.square([1, 2, 3])
[1, 4, 9]
iex> MySquarer.square([-1, -2, -3])
[1, 4, 9]
```

# まとめ

Elixirでパターンマッチングがどのような意味を持ちどれほど使えるものかご理解いただければ幸いです。再帰呼び出しはトリッキーですがElixirのパターンマッチングを使うことで多少は読んで理解するのが簡単になります。