技術メモ

プログラミングとか電子工作とか

Elixir入門(第四章 パターン・マッチング)

f:id:ysmn_deus:20190122112104p:plain

どうも、靖宗です。
途中から日本語が消失してますが、めげずに学習します。

マッチ演算子

Elixirでは=はマッチ演算子という名称だそうです。
単純に考えれば代入のような感じですが

iex> x = 1
1
iex> 1 = x
1
iex> 2 = x
** (MatchError) no match of right hand side value: 1

と、1 = xという式は問題無く通ってます。2 = xは、式として間違っているというエラーではなく、マッチしないというエラーのようです。

パターン・マッチ

Elixirではどうやら型?構造があっていればマッチングする様で、複雑な構造を解体するのにパターン・マッチが利用できるそうです。

iex(1)> {a, b, c} = {:hello, "world", 42}
{:hello, "world", 42}
iex(2)> a
:hello
iex(3)> b
"world"
iex(4)> c
42

異なる型やサイズの違うタプルをマッチングするとエラーを吐く。

iex(5)> iex> {a, b, c} = {:hello, "world"}
** (CompileError) iex:5: cannot invoke remote function :erlang.>/2 inside a match

iex(5)> {a, b, c} = [:hello, "world", 42]
** (MatchError) no match of right hand side value: [:hello, "world", 42]
    (stdlib) erl_eval.erl:453: :erl_eval.expr/5
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4

値を指定してパターンマッチを使う云々の箇所はよく分からない。
このマッチングにうまみがあるんだろうか?後々分かるといいな・・・

iex> {:ok, result} = {:ok, 13}
{:ok, 13}

リストもパターンマッチ可能

iex(5)> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex(6)> a
1
iex(7)> b
2
iex(8)> c
3
iex(9)> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex(10)> head
1
iex(11)> tail
[2, 3]

[head | tail]という形式がでてるが、これはリストの先頭に値を付与するのにも利用できるようで。

iex(12)> list = [1, 2, 3]
[1, 2, 3]
iex(13)> [0 | list]
[0, 1, 2, 3]

ここから先は日本語化されてないので私の独自解釈の恐れがあります。

ピン・オペレータ(The pin operator)

Elixirの中では何度でも変数が書き換え可能。

iex(15)> x = 1
1
iex(16)> x = 2
2

だが、変数を左に書いてマッチングしたいときに再代入されちゃう

iex(16)> x = 2
2
iex(17)> {y, x} = {2, 1} # ここで、x = 1の時にマッチングしてyに2を入れたい。が、再び代入が起こる
{2, 1}
iex(18)> x
1

これを防ぐのがピンオペレータ^である。

iex(24)> x = 1
1
iex(25)> {y, ^x} = {2, 1}
{2, 1}
iex(26)> {y, ^x} = {2, 2}
** (MatchError) no match of right hand side value: {2, 2}

まだ使いどころ分からないけど覚えておこう。

パターンマッチングの時に、気にしない箇所はアンダースコア_で無視できるみたい。

iex(26)> [ h | _ ] = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
iex(27)> h
1

アンダースコアは単体では読み出せない特殊な変数。単体で読み出したいことなんて無いと思うので無視!

パターンマッチングは式の評価前を見てる様で、関数=数値 なんかはマッチングしない。

iex(28)> length([1, [2], 3])
3
iex(29)> length([1, [2], 3]) = 3
** (CompileError) iex:29: cannot invoke remote function :erlang.length/1 inside a match

まだ基礎文法で全然面白くないけど、Ruby知らないしこの辺すっ飛ばしてると痛い目みそうなので読み込んでいきます。