『プログラミング  Elixir』第2章パターンマッチ:練習問題

『プログラミング Elixir』の練習問題を解く。
Q.で問題を示し、#で自分が回答を導くまでの考えを示し、A.で実行結果/回答を示す

## 練習問題:PatternMatching-1


### Q.次のどれがマッチするだろうか
```
Q1. a = [1, 2, 3]
Q2. a = 4
Q3. 4 = a
Q4. [a,b] = [1, 2, 3]
Q5. a = [ [ 1, 2, 3 ] ]
Q6. [a] = [ [ 1, 2, 3 ] ]
Q7. [[a]] = [ [ 1, 2, 3 ] ]
```

### ・Answer
・パターンマッチは、パターン（左辺）と値（右辺）の構造が同じで、かつパターンのそれぞれの項が、値の中の対応する項とマッチするときに成立する

```
Q1. a = [1, 2, 3]
#変数aは1つの右辺の1つの配列とマッチする
A1. Match: a => [1, 2, 3]

Q2. a = 4
#左辺aは右辺の1つの値4とマッチする
A2. Match: a => 4

Q3. 4 = a
#基本的に左辺の値4は右辺aとはマッチしないが、事前にaを4にマッチさせておくとこの例でもマッチする
A3. ** (CompileError) iex: undefined function a/0

Q4. [a,b] = [1, 2, 3] 
#左辺の配列にはaとbの2つの項があるが、値（右辺）の項は3つあり、構造が異なるためマッチしない
A4. ** (MatchError) no match of right hand side value: [1, 2, 3]

Q5. a = [ [ 1, 2, 3 ] ] 
#左辺はaのみで、値は配列[1,2,3]を持つ配列1つだけで構造は同じで、aは配列[1,2,3]を持つ配列1つとマッチする
A5. Match: a => [[1, 2, 3]]


Q6. [a] = [ [ 1, 2, 3 ] ] 
#左辺は配列だが項はaのみで、右辺も配列だが項は配列[1,2,3]の1つのみであり左辺と右辺の構造は同じ。よって左辺の項aは配列[1,2,3]とマッチする
A6. Match: a => [1,2,3]


Q7. [[a]] = [ [ 1, 2, 3 ] ] 
#左辺は配列[a]を持つ配列、右辺は配列[1,2,3]を持つ配列で、左辺aに対して右辺が1,2,3の3つある構造となっているため、マッチしない
A7. ** (MatchError) no match of right hand side value: [[1, 2, 3]]

```
## 練習問題:PatternMatching-2
・変数の束縛はマッチ中では１度だけ
・キャレット(^)を使うと、変数の現在の値をパターンの中で使えるようになる

```elixir:例
iex> a = 1
1

iex> [^a, 2] = [5, 2] #^aは既にあるaの値を使うから、その中の値は１
**MatchError

iex> [^a, 2] = [1, 2]
[1, 2]

```

### Q.次のどれがマッチするだろうか
```
Q1. [ a, b, a ] = [ 1, 2, 3 ]
Q2. [ a, b, a ] = [ 1, 1, 2 ]
Q3. [ a, b, a ] = [ 1, 2, 1 ]

```

### ・Answer
```
Q1. [ a, b, a ] = [ 1, 2, 3 ]
#このマッチの中では、左辺の1つ目の項であるaは１にマッチしている。マッチ中では変数の束縛は１度だけのため、左辺3つ目の項aも１にマッチする必要があるが、上記Q1では対応する右辺の3つ目の項の値は3担っているため、マッチしない.
A1. ** (MatchError) no match of right hand side value: [1, 2, 3]


Q2. [ a, b, a ] = [ 1, 1, 2 ]
#Q1と同様に、左辺の1つ目の項でaは１とマッチしているため、左辺3つ目の項aと右辺3つ目の項２がマッチしない 
A2. ** (MatchError) no match of right hand side value: [1, 1, 2]


Q3. [ a, b, a ] = [ 1, 2, 1 ]
#左辺でaが項として２度出ているが、そのどちらも値は1であり、「変数の束縛はマッチ中で１度だけ」という条件も満たしており、マッチする
A3. Match

```

## 練習問題:PatternMatching-3

### Q.変数aが、もともと２であるとき、次のどれがマッチするか

```
Q1. [ a, b, a ] = [ 1, 2, 3 ]

Q2. [ a, b, a ] = [ 1, 1, 3 ]

Q3. a = 1

Q4. ^a = 2

Q5. ^a = 1

Q6. ^a = 2 - a
```

### ・Answer

```
Q1. [ a, b, a ] = [ 1, 2, 3 ]
#変数の束縛はあくまでマッチの中で１度だけであり、左辺の1つ目の項aは右辺の1つ目の項1とマッチする。
が、左辺3つ目の項aについては「変数の束縛はマッチ中で１度だけ」という条件があるため、右辺3つ目の項3とはマッチせず、MatchErrorになる
A1. ** (MatchError) no match of right hand side value: [1, 2, 3]

Q2. [ a, b, a ] = [ 1, 1, 2 ]
#変数aがもともと２であっても、あくまでも「変数の束縛はマッチ中１度だけ」なので左辺1つ目の項aは右辺1つ目の項１とマッチする。
が、左辺3つ目の項もaで、それに対応する右辺の項は2であり、既にこのマッチ中でのaは１とマッチしているため、MatchErrorになる
A2. ** (MatchError) no match of right hand side value: [1, 1, 2]

Q3. a = 1
#変数は新たな値とマッチし直すことができるため、 a = 1はマッチする
A3. Match

Q4. ^a = 2
#変数aはもともと２であり、^aもその中の値は２であるため、マッチする
A4. Match

Q5. ^a = 1
#変数aはもともと2であるが、新たに異なる値とマッチさせることもできる。
が、接頭語としてキャレットを変数につけた場合には、変数の現在の値を使うことになる。
そのため^aの中の値は2であり、^a = 1はMatchErrorになる
A5. ** (MatchError) no match of right hand side value: 1

Q6. ^a = 2 - a
# ^aの中の値は２で、右辺は計算すると０になり、マッチしない
A6. ** (MatchError) no match of right hand side value: 0
```

## *等号記号の別の見方
Elixir: 等号記号は左辺と右辺をマッチさせる、束縛させるもの
Erlang的な等号記号の見方: 等号記号を代数での等号記号の使われ方に例える
`例） x = a + 1`

代数では、例えば`a = 5`の時、上記の式では`x = 6`というように答えを求める。つまり、その値をx自体に代入したりはせず、単に`x`の値と`a + 1`の値が同じであることを表す。
そのため、xの値がわかっていれば、aの値を求めることもできる。
`例)x=6のとき 6 = a + 1 -> a = 5`
・Javaなどの手続き型プログラミングでは代数的な等号記号の意味を忘れる必要があったが、Elixirにおいては「代数的な意味を忘れるのを忘れる」必要がある