ガードは関数のパターンマッチングをより詳細に記述するためのものです。
パターンマッチではどうしても解決できない処理をガードに記します。
パターンマッチで書けるものをガードに処理させるのは無駄ですので、可能ならパターンマッチを使うべきです。
ガードの書式は
パターン1 ガード1 -> .....
パターン1 ガード2 -> .....
パターン2 ガード1 -> .....
となっています。
ガードの部分は when
を使って記述します。
実際に例を見てみましょう。
bigger(X , Y) when X > Y ->
X;
bigger(X , Y) when X < Y ->
Y;
bigger(X , _Y) ->
io:format("same~n",[]),
X.
4> mod:bigger(3,5).
5
5> mod:bigger(8,2).
8
6> mod:bigger(6,6).
same
6
7> mod:bigger(dog,cat).
dog
関数名の後ろにある、
when 条件
によって、節が選択されていることがわかりますね。
パターンにマッチしたのに、そのガードの全てに適合しなかった場合はエラーとなります。
最後のパターンは予期しなかった結果ですね。
数字の大小を比較する関数が、アトム同士を比較してしまっています。
これを防ぐためにはX,Yは整数で、かつ、 〜 であるというような書き方をしなければいけません。
論理積とは全ての条件がtrueだとtrueになり、その他は全てfalseであるというものです。
これをErlangのガードの中で使うことができます。
ガード式1 , ガード式2
として記述します。
bigger2(X,Y) when is_integer(X),is_integer(Y), X>Y ->
X;
bigger2(X,Y) when is_integer(X),is_integer(Y) ->
Y;
bigger2(_,_) ->
io:format("X or Y or Both is not Integer~n",[]).
「is_integer()」は引数が整数型だとtrueを返します。
9> mod:bigger2(3,5).
5
10> mod:bigger2(dog,cat).
X or Y or Both is not Integer
ok
論理和とは、条件が一つでもtrueだとtrueになるというものです。
ガードの中に論理和を利用することができます。
ガード式1 ; ガード式2
として記述します。
animal(X) when dog =:= X; cat =:= X ->
io:format("dog or cat~n",[]);
animal(X) when is_atom(X) ->
io:format("other~n",[]);
animal(X) ->
X.
「=:=」は左辺と右辺が同じ値ならtrueを返します。
11> mod:animal(cat).
dog or cat
ok
12> mod:animal(human).
other
ok
13> mod:animal(3).
3
14> mod:animal(dog).
dog or cat
ok