もやもやエンジニア

IT系のネタで思ったことや技術系のネタを備忘録的に綴っていきます。フロント率高め。

Elixir 入門 その3 - パターンマッチの基本

パターンマッチの基本

The match operator

  • Elixirにおける = はmatch operator
  • 代入ではなくパターンマッチにおける束縛を意味する
# これは一見代入しているように見える
iex> x = 1
1

# xに1が束縛された状態で逆にしても通る
iex> 1 = x
1

# これは通らない。1が束縛された x と 2 はマッチしない
iex> 2 = x
** (MatchError) no match of right hand side value: 2

# 左辺がvariableであれば再度束縛される
iex> x = 2
2

# pin operator をつけると防いでくれる
iex> ^x = 3
** (MatchError) no match of right hand side value: 3

# 今は2が束縛されているのでマッチする
iex> 2 = x
2

パターンマッチ

  • Tupleでも使える。これが強力。
iex> {a, b, c} = {:hello, "world", 42}
{:hello, "world", 42}

iex> a
:hello

iex> b
"world"

iex> c
42

# 逆にしても通る
iex> {:hello, "world", 42} = {a, b, c}
{:hello, "world", 42}

# これはTuple内の要素数が異なるのでマッチしない
iex> {a, b} = {:hello, "world", 42}

# 要素数が同じでも値が異なればマッチしない
iex> {a, b, c} = {:hello, "world", 444}
  • 応用すると以下の様なことができる
iex> {:ok, result} = {:ok, "hoge"}
{:ok, "hoge"}

# resultにはhogeが束縛される
iex> result
hoge

# これはtupleの1つめのatomが:ngと:okでマッチしない
iex> {:ng, result} = {:ok, "hoge"}
** (MatchError) no match of right hand side value: {:ok, "hoge"}
  • Listでもパターンマッチは使える
iex> [x,y,z] = [1,2,3]
[1, 2, 3]

iex> x
1

iex> y
2

iex> z
3

iex> [1,2,3] =  [x,y,z]
[1, 2, 3]

# 他の要素がマッチしていれば束縛も可能
iex> [1, x, 3] = [1, 5, 3]
[1, 5, 3]

# xには5が束縛される
iex> x
5

# Haskellにもあったけど [ head | tail ]のマッチングもできる
iex> [head | tail] = [1, 2, 3]
[1, 2, 3]

iex> head
1

iex> tail
[2, 3]

# 空Listはマッチしない
iex> [head | tail] = []
** (MatchError) no match of right hand side value: []

underscore

  • 特別な意味を持つvariableでワイルドカードにおける * のような存在。
  • なんにでもマッチするが、上の例で出てきたように _ にマッチした値が束縛されることはない
iex> [1, _, 3] = [1, 2, 3]
[1, 2, 3]

iex> _
** (CompileError) iex:28: unbound variable _

function

  • 関数の実行結果のマッチもできる。
iex> 3 = length([1,[2],3])
3

# ただし関数が左辺に来るとできない
iex> length([1,[2],3]) = 3
** (CompileError) iex:1: illegal pattern