特徴的な演算子
基本的な演算子の挙動は他言語と同じなので,ここでは特徴的な演算子や,他言語と異なる注意すべき演算子について解説する.
文字列の結合
文字列の結合には<>
という演算子を用いる
iex> "hello" <> " " <> "world"
"hello world"
iex> hello <> " world" # 変数とも結合できる(helloにはあらかじめ"hello"が束縛されている)
"hello world"
文字列の結合自体は,式を埋め込む形でも行える
iex> hello = "hello"
"hello"
iex> "#{hello} world"
"hello world"
#{}
の中身は評価されて表示されるので,こんなことも可能
iex> he = "he"
"he"
iex> llo = "llo"
"llo"
iex> "#{he <> llo} world"
"hello world"
マッチ演算子(=
)
Elixirでは=
は代入の意味を持ちません.演算子の両辺を比較(パターンマッチ)するマッチ演算子と呼ばれます.
- マッチできない組み合わせでマッチ演算子を用いると「代入が出来ない」ではなく「マッチエラー」というエラーが出力されます.
- マップの比較をするとき,左辺に存在しないkeyは無視して比較が行われます(逆のパターンはマッチエラーとなります)
iex> 1 = 1
1
iex> 1 = 2
** (MatchError) no match of right hand side value: 2
iex> %{a: 1} = %{a: 1, b: 2}
%{a: 1, b: 2}
iex> %{a: 1, b: 2} = %{a: 1}
** (MatchError) no match of right hand side value: %{a: 1}
変数に値を格納したいときに書く処理は他言語と変わりません.そのかわり,式の解釈が変わります.
iex> x = 3 # 変数xに3という値が「束縛(bind)」された
3
マップのマッチ
「代入」ではなく「束縛」なので,リストやマップから値を取り出すときにとても柔軟な書き方が可能になります.(超大事.私が他言語に戻れなくなった理由です)
iex> %{a: a, b: b} = %{a: 1, b: 2, c: 3}
%{a: 1, b: 2, c: 3}
iex> a
1
iex> b
2
iex> %{x: %{y: y}} = %{x: %{y: 1}} # 入れ子構造でもOK!
%{x: %{y: 1}}
iex> y
1
リストのマッチ
リストのマッチも同様に複数の要素をマッチすることが出来ます.
iex> [a, b] = [1, 2]
[1, 2]
iex> a
1
iex> b
2
その他,リストは特殊な書き方でマッチすることが出来ます.
iex> [head | tail] = [1, 2, 3, 4, 5] # 先頭とそれ以外を分離したい
[1, 2, 3, 4, 5]
iex> head
1
iex> tail
[2, 3, 4, 5]
|
はそれ以降とを分けるための記法なので,少しトリッキーなことも出来ます.
iex> [head1, head2 | tail] = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
iex> head1
1
iex> head2
2
iex> tail
[3, 4, 5]
不要な値を無視する
マップでは必要なkeyのみ取り出せば良いですが,リストでは順序が大事なので,使わない要素もマッチさせる必要があります.
- 使わない変数に束縛して放置すると言う方法も採れますが,エレガントではありません(warningが出ますし,可読性も下がってしまいます)
- このようなケースではアンダースコア
_
を用います
iex> [a, _, c] = [1, 2, 3] # 1番目と3番目の要素だけ欲しい
iex> [a, 2, c] = [1, 2, 3] # 2番目を無視できる(束縛せずに取り出せる)が,2番目の要素が未知の場合使えない
練習問題
パターンマッチ1行でやってみましょう
3
を変数x
に拘束%{a: 1, b: 2, c: 3}
:a
を変数x
,2.3
を変数y
に拘束(1
と"a"
は何にも拘束しない)[1, :a, "a", 2.3]
2
を変数x
,4
を変数y
,5~10
のリストをz
に拘束(1
と3
は何にも拘束しない)[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
を変数x
,4
を変数y
に拘束%{a: %{b: 1, c: 2, d: [3, 4, 5]}}
2
を変数x
,[]
(空の配列)をy
に拘束[1, 2, 3]
指定されたパターンにのみで課題が解けるパターンマッチ1行を作ってみましょう(それ以外のパターンでは
MatchError
となれば正解です)最初のパターンのみで
3
を変数x
に拘束(他の要素は拘束しない)[1, 3, 2]
[1, 2]
[1, 3, 1]
最初のパターンのみで
3
を変数x
に拘束(1
と2
は拘束しない._
を使った無視もしてはいけない)%{"a" => 1, "b" => 2, "c" => 3}
%{"a" => 1, "b" => 2}
%{:a => 1, :b => 2, :c => 3}
%{a: 1, b: 2, c: 3}
最初と上から2つめのパターンで
3
を変数x
に拘束(他の要素は拘束しない)[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 2, 3]