# 関数の構文

> Source: https://www.ymotongpoo.com/works/lyse-ja/05_syntax_in_functions/


## パターンマッチ

<img src="snail1.png" class="align-left" alt="image" />

いまやコードをコンパイルして保存することが出来るようになったので、もっと複雑な関数を書き始めることができます。 これまで書いてきた関数は究極的に簡単で、ちょっと面白くないものでしたね。 もっと面白いものを作りましょう。最初の関数は相手の性別によって違った風に挨拶する必要があります。 大抵の言語ではこのような形で書くでしょう：

``` ruby
function greet(Gender,Name)
    if Gender == male then
        print("Hello, Mr. %s!", Name)
    else if Gender == female then
        print("Hello, Mrs. %s!", Name)
    else
        print("Hello, %s!", Name)
end
```

パターンマッチがあるので、Erlangではこう言った決まり文句は省くことが出来ます。Erlangでは同様の関数は次のようになります：

``` erlang
greet(male, Name) ->
    io:format("Hello, Mr. ~s!", [Name]);
greet(female, Name) ->
    io:format("Hello, Mrs. ~s!", [Name]);
greet(_, Name) ->
    io:format("Hello, ~s!", [Name]).
```

Erlangでは表示関数は他の言語に比べてすごくブサイクだと認めます。しかし、そこは問題ではありません。 ここでの一番の違いは関数のどの部分を使うかとどんな値が必要かをパターンマッチを使って同時に定義したことにあります。 値を束縛してそれを比較する必要などないのです！なのでこういうふうに書く代わりに：

``` ruby
function(Args)
    if X then
Expression
    else if Y then
Expression
    else
Expression
```

Erlangではこう書きます：

``` erlang
function(X) ->
    Expression;
function(Y) ->
    Expression;
function(_) ->
    Expression.
```

これで同じような結果が得られますが、ずっと宣言的なスタイルです。 それぞれの関数宣言が関数節と呼ばれています。関数節はセミコロン（;）で区切られ、関数宣言でまとめられます。 関数宣言は一つの大きな文として捉えられ、それが最後の関数節がピリオドで終わっている理由です。 トークンをワークフローの定義に使うのは「おかしい」ですが、慣れるでしょう。 少なくとも、慣れるべきです。なぜならそれ以外に方法はないからです！

> [!NOTE]
> `io:format` のフォーマットは文字列で置き換えられるトークンを使っています。 トークンを記述する際に使う文字はチルダ（ `~` ）です。 `~n` のようないくつかのトークンは組み込みです。 `~n` は改行に変換されます。 他のトークンはたいていデータをどのように表示するか記述します。 `io:format("~s!~n,["Hello"]).` は `~s` というトークンを含んでいて、これは文字列やビット文字列を引数にとります。そして `~n` がそれに続きます。 最終的に出力されるメッセージは `"Hello!\n"` となります。他によく使われるトークンは `~p` です。これはErlang項をいい感じに表示してくれます。（全部にインデントを入れてくれます）
>
> `io:format` 関数は入出力に深く触れるあとの章で詳細を見るとして、しばらくはこれらのどれかを使っていましょう：`io:format("~s~n",[<<"Hello">>])`, `io:format("~p~n",[<<"Hello">>])`, `io:format("~~~n")`, `io:format("~f~n", [4.0])`, `io:format("~30f~n", [4.0])` これで大体この関数ができるすべてのことがわかります。これらは他の多くの言語にある `printf` 関数のようなものです。 もし入出力の章まで待てなければ [オンラインドキュメント](http://erlang.org/doc/man/io.html#format-3) を読んでもいいでしょう。

関数内でのパターンマッチはより複雑にかつ強力にできます。ちょっと前の章で触れたんですが、リストのheadとtailを得るためにパターンマッチを使いました。これをやってみましょう！ 新しいモジュール [functions](http://learnyousomeerlang.com/static/erlang/functions.erl) を始めてみましょう。ここでたくさんの関数を書いてパターンマッチを堪能しましょう：

``` erlang
-module(functions).
-compile(export_all). %% replace with -export() later, for God's sake!
```

最初に各関数は `head/1` です。これは `erlang:hd/1` のようにリストを引数として受け取りその最初の要素を返します。 cons演算子を使って次のように書くことが出来ます：

``` erlang
head([H|_]) -> H.
```

シェルで `functions:head([1,2,3,4]).` と書けば（モジュールがコンパイル済みの場合）、予想通り '1' が返ってきます。結果として2番目の要素を得るには、次のような関数を書けるでしょう：

``` erlang
second([_,X|_]) -> X.
```

このリストはパターンマッチのためにErlangによって解体されます。シェルで試してみましょう！

``` erlang
1> c(functions).
{ok, functions}
2> functions:head([1,2,3,4]).
1
3> functions:second([1,2,3,4]).
2
```

1000までやるのは非実用的ですが、リストに対してやりたいだけこれを繰り返すことができます。 これは再帰関数を書くことで修正することができますが、それについてはあとで触れましょう。 いまはパターンマッチに集中しましょう。 [（本当に）始めましょう！](../03_starting_out_for_real/) で話したように、自由な変数と束縛された変数のコンセプトは関数でも生きています。 関数に渡された2つのパラメータを比較して、それが同じかどうかを知ることができます。これには2つの引数を取って、同じかどうかを教える関数 `same/2` を書きましょう：

``` erlang
same(X,X) ->
    true;
same(_,_) ->
    false.
```

とてもシンプルですね。この関数がどのように動作するか説明する前に、念のため変数の束縛と未束縛に関して再度見てみましょう：

![image](un-bound1.png)

ここで、花婿は悲しがっています。なぜならErlangでは変数は決して値を変更できないからです：自由がない！冗談はさておき、未束縛の変数は値が付いていない変数のことをいいます。（上の絵の右側にあるホームレスのような感じです） 変数を束縛するというのは、単純に値を未束縛の変数にくっつけることを言います。 Erlangでは、束縛されている変数に値を与えようとすると、新しい値が束縛されている値と同じでない限りエラーが発生します。 上の絵の左の男性が双子のどちらかと結婚したとしましょう。もし双子の片割れがきたら、彼は気づかずそのまま過ごすでしょう。 違った女性がきたら、彼は文句を言うでしょう。このへんが曖昧な場合は [変化できない変数](../03_starting_out_for_real/) を読んでください。

コードに戻りましょう： `same(a,a)` を呼び出したときに起きるのは、まず最初のXが未束縛だとみなされます。そして自動的に値aを束縛します。Erlangが次の引数に行ったときに、Xはすでに束縛されていると認識します。そして、2番目の引数に渡された値と比較します。パターンマッチが成功したら関数は `true` を返します。 もし2つの関数が同じでなかったら、このパターンマッチは失敗となって次の関数節に進みます。2番目の関数節では、引数に何が来ても気にしません。（あなたが行き遅れなら、選り好みしている場合じゃないでしょう！）そして `false` を返します。 この関数はどんな型のデータでも動作します。リストでも単一の変数でもです。 もうちょっと進んだ例を見てみましょう。次の関数は日付を表示しますが、正しくフォーマットされていなければなりません：

``` erlang
valid_time({Date = {Y,M,D}, Time = {H,Min,S}}) ->
    io:format("The Date tuple (~p) says today is: ~p/~p/~p,~n",[Date,Y,M,D]),
    io:format("The time tuple (~p) indicates: ~p:~p:~p.~n", [Time,H,Min,S]);
valid_time(_) ->
    io:format("Stop feeding me wrong data!~n").
```

関数の先頭で `=` 演算子を使って、タプルの中身(`{Y,M,D}`)とタプル全体(Date)をパターンマッチ出来ていることに注目してください。この関数は次の用にテストできます：

``` erlang
4> c(functions).
{ok, functions}
5> functions:valid_time({{2011,09,06},{09,04,43}}).
The Date tuple ({2011,9,6}) says today is: 2011/9/6,
The time tuple ({9,4,43}) indicates: 9:4:43.
ok
6> functions:valid_time({{2011,09,06},{09,04}}).
Stop feeding me wrong data!
ok
```

問題がありました！この関数は値に文字列やアトムでもなんでも受け付けられるます。タプルが `{{A,B,C},{D,E,F}}` の形をしていれば大丈夫です。 これがパターンマッチの一つの限界を示しています。パターンマッチは、きっちり決まった値、たとえばわかった数のアトムとか、リストのhead\|tailなどの絶対的な値、N個の要素のタプル、あるいは任意値（ `_` や未束縛の変数）です。 この問題を解決するために、ガードを使います。

## ガードだ、ガード！

<img src="driving-age1.png" class="align-right" alt="image" />

ガードは関数でより詳細を記述するための追加の節です。 上で書いたように、パターンマッチはある程度制限があって、値の範囲や特定の型のデータを表現することはできません。 表現できない概念は数え上げです：この12歳のバスケットボール選手はプロと一緒にプレーするには背が低すぎるんでしょうか？ この距離は逆立ちで歩くには長すぎるんでしょうか？あなたは車を運転するには若すぎる？あるいは老いすぎてる？ あなたは質問には簡単なパターンマッチでは答えられないでしょう。 言いたいことは、例えば車の運転の質問であればこんな感じに書けます：

``` erlang
old_enough(0) -> false;
old_enough(1) -> false;
old_enough(2) -> false;
...
old_enough(14) -> false;
old_enough(15) -> false;
old_enough(_) -> true.
```

しかしこれは全然使い物になりません。やりたければやってもかまいませんが、あなたは永遠にコードの中でひとりぼっちになりますよ。 ちゃんとお友達を作りたかったら [guards](http://learnyousomeerlang.com/static/erlang/guards.erl) モジュールをはじめて、この問題を解決する「正しい」方法を見てみましょう：

``` erlang
old_enough(X) when X >= 16 -> true;
old_enough(_) -> false.
```

はい、これで終わりです！見て分かるように、ずっと短くてすっきりしています。 ガード表現の基本的なルールは成功時に `true` を返さなければいけないことです。 もし `false` が返ってきたらガードは失敗して、例外を投げます。 104歳以上の人が運転するのを禁止してみましょう。ここで運転可能な年齢は16歳から104歳になりました。 これを考慮に入れなければいけないんですがどうしたらいいんでしょうか？ 2番目のガード節を加えましょう：

``` erlang
right_age(X) when X >= 16, X =< 104 ->
    true;
right_age(_) ->
    false.
```

カンマ（,）は `andalso` 演算子と同じように振る舞い、セミコロン（;）は `orelse` のように振る舞います。 （"\`（本当に）始めましょう！ \<../03_starting_out_for_real/\>\`\_"で触れています）両方のガード式ともにガード全体で成功しなければいけません。 逆の意味でも関数を表現できます：

``` erlang
wrong_age(X) when X < 16; X > 104 ->
    true;
wrong_age(_) ->
    false.
```

<img src="guard1.png" class="align-left" alt="image" />

これでも正しい結果を取得できます。テストしてみてもいいでしょう（テストは常にすべきです！） ガード式では、セミコロン（;）は `orelse` 演算子のように動作します。もし最初のガードが失敗したら、2番目のガードを試して、それでもだめなら次、という具合にガードが成功するまで続けて、最後は失敗します。

関数内で比較や真偽をするときにいくつかの関数を使うことが出来ます。数学的表現(`A*B/C >= 0`)やデータ型に関するもの（ `is_integer/1`, `is_atom/1` ）があります。（あとの章でこれらについてはやります） ガードの欠点は、副作用を考えてユーザ定義の関数を受け入れないことです。 Erlangは純粋な関数型言語ではありません。（ [Haskell](http://learnyouahaskell.com/) とは違います） なぜならErlangは多くの副作用に依存しているからです。I/Oもできます。アクター間でメッセージを送ることもできます。 したければエラーを投げることもできます。 ガードの中で使っている関数が文字を表示するかいなか、あるいは重要なエラーをキャッチするのか、その関数が使われてる関数節ごとに定義するのに簡単な方法がありません。 なので代わりにErlangではあなたを信用しないことにしました！（それが正しいと思います！）

こうは言いましたが、ガードが出てきたときに理解できるようにガードの基本的な構文は十分理解すべきです。

> [!NOTE]
> ガードでの `,` と `;` を `andalso` と `orelse` と比較しました。 しかしこれらは全く一緒というわけではありません。前者2つは例外をキャッチする一方で、後者2つはしません。 これはつまり、もしガード `X >=N; N >= 0` の最初のほうでエラーが投げられても2番目は評価されてガードは成功します。 しかしガード `X >= N orelse N >= 0` の最初の部分でエラーが投げられた場合、2番目はスキップされて、ガード全体として失敗します。
>
> しかしながら（常に「しかしながら」があるのですが）、 `andalso` と `orelse` だけガードの中で入れ子に出来ます。 つまり `(A orelse B) andalso C` は適切だということです。 `(A; B), C` は不適です。 異なった使い方ができるので、一番の戦略は必要に応じて混ぜて使うことです。

## Ifってなんだ!?

`if` はガードのように振る舞い、ガードと同じような構文を使います。しかし関数節の先頭の外側で使います。 実際、 `if` 節はガードパターンと呼ばれます。Erlangの `if` はあなたが他の言語でみてきた `if` とは異なります。 他の言語での `if` と比較すると、他の言語での `if` は違う名前を持った奇妙な怪物のようです。 Erlangの国に入ったなら、今まで `if` について知っていたことをドアの前に置きさってしまいましょう。 そして席に座って一緒にドライブに行きましょう！

ガードとif式がどれくらい似ているか見てみましょう。次の例を見てください：

``` erlang
-module(what_the_if).
-export([heh_fine/0]).


heh_fine() ->
    if 1 =:= 1 ->
        works
    end,
    if 1 =:= 2; 1 =:= 1 ->
        works
    end,
    if 1 =:= 2, 1 =:= 1 ->
        fails
end.
```

これを [what_the_if.erl](http://learnyousomeerlang.com/static/erlang/what_the_if.erl) として保存して、次を試してみましょう：

``` erlang
1> c(what_the_if).
./what_the_if.erl:12: Warning: no clause will ever match
./what_the_if.erl:12: Warning: the guard for this clause evaluates to 'false'
{ok,what_the_if}
2> what_the_if:heh_fine().
** exception error: no true branch found when evaluating an if expression
     in function  what_the_if:heh_fine/0
```

<img src="labyrinth1.png" class="align-right" alt="image" />

あらら！コンパイラが、12行目(`1 =:= 2, 1 =:= 1`)のifは `false` になってしまうガードしかないのでマッチしないということで警告をだしています。 Erlangでは、すべてのものが何かを返さなければいけません。そして `if` 式もこの例外ではありません。 このようなことから、Erlangではガードが成功できないとわかったときにはクラッシュします。何かを返せないのです。 したがって、何がっても成功するようにcatch-allを追加する必要があります。 大抵の言語では、これは `else` と呼ばれています。Erlangでは 'true' を使います。 （これがなぜErlang VMがおかしくなったときに"no true branch found"と投げる理由です）

``` erlang
oh_god(N) ->
    if N =:= 2 -> might_succeed;
        true -> always_does  %% this is Erlang's if's 'else!'
    end.
```

そして、新しい関数をテストすると（古い関数は警告を投げ続けます。無視するか、「すべからず」として残しておきましょう）：

``` erlang
3> c(what_the_if).
./what_the_if.erl:12: Warning: no clause will ever match
./what_the_if.erl:12: Warning: the guard for this clause evaluates to 'false'
{ok,what_the_if}
4> what_the_if:oh_god(2).
might_succeed
5> what_the_if:oh_god(3).
always_does
```

if式の中でどのようにたくさんのガードを使うかの例となる関数があります。 この関数はどんな式も必ず何かを返さなければいけないということも示しています。 Talkはif式の結果を束縛していて、それをタプル内で文字列と結合しています。 このコードを読んだ時に、 `true` ブランチがなかった場合、Erlangにはナル値（つまり、LISPでのnil、CでのNULL、PythonでのNoneなどです）のような物はないことを考えれば困ったことになるのがすぐに分かると思います：

``` erlang
%% note, this one would be better as a pattern match in function heads!
%% I'm doing it this way for the sake of the example.
help_me(Animal) ->
    Talk = if Animal == cat  -> "meow";
              Animal == beef -> "mooo";
              Animal == dog  -> "bark";
              Animal == tree -> "bark";
              true -> "fgdadfgna"
           end,
    {Animal, "says " ++ Talk ++ "!"}.
```

試してみましょう：

``` erlang
6> c(what_the_if).
./what_the_if.erl:12: Warning: no clause will ever match
./what_the_if.erl:12: Warning: the guard for this clause evaluates to 'false'
{ok,what_the_if}
7> what_the_if:help_me(dog).
{dog,"says bark!"}
8> what_the_if:help_me("it hurts!").
{"it hurts!","says fgdadfgna!"}
```

あなたもなぜ'else'にかわって'true'になった理由を知りたがっている多くのErlangプログラマの一人でしょう。 結果として、それはとても有名な話になっています。 Richard O'Keefeが次のような回答をErlangメーリングリストに投げました。 うまく表現できないので直接引用します。

> [!NOTE]
> とても「有名な」ではありますが、だからと言って'else'はいいとは思いません。 Erlangで'else'と'; true -\>' と書くのはとても簡単なことだと知っていますが、心理的には数十年にわたるプログラミングの結果、それはあまり得策ではないとわかりました。私は次のように置換えをするようになりました：
>
> ``` none
> by
> if X > Y -> a()     if X > Y  -> a()
> ; true  -> b()      ; X =< Y -> b()
> end                 end
>
> if X > Y -> a()     if X > Y -> a()
> ; X < Y -> b()      ; X < Y -> b()
> ; true  -> c()      ; X ==Y -> c()
> end                 end
> ```
>
> この書き方は *書いているときは* イライラしますが、 *読むとき* は本当に助かります。

'else' または 'true' ブランチは結局のところ「避けられるべき」なのです。 `if` は通常論理的にすべてのパターンを網羅しておいたほうが *catch-all* 節に頼るよりも読みやすくなります。

上で述べたように、ガード式内で使える関数は限られています。（ [型](../06_types/) でさらに触れます） ここがErlangが魔法を書けられるべき制限がかかった部分です。ここでそれをあなたにあげましょう。 `case` 式です！

> [!NOTE]
> ここで `what_the_if.erl` 内の関数で示された恐ろしいものは、 `if` 言語が他の言語での `if` の立場で書かれた場合、どんな恐ろしいことが起きるか表したものです。 Erlangのコンテキストでは、紛らわしい名前を持った完全に論理的な構造物だとわかりました。

## もしも...の場合 (In Case ... of)

もし `if` 式がガードのようなら、 `case ... of` 式は関数のようです。引数を持った複雑なパターンマッチや、その上にガードすら持てるのです！

構文がだいぶ分かってきたと思うので、もう多くの例は必要としません。この節では、並び直していないリストとして表現されたセット（一意な値の集合）のためのappend関数を書きましょう。 これは効率の意味では最悪の実装になていますが、ここで必要なのは構文なのでその例を示します：

``` erlang
prepend(X,[]) ->
    [X];
prepend(X,Set) ->
    case lists:member(X,Set) of
        true  -> Set;
        false -> [X|Set]
    end.
```

空のセット（リスト）と追加される項Xを渡せば、Xだけを含むリストを返してきます。あるいは関数 `lists:member/2` が要素がリストにあるかどうか確認し、もし存在するとなればtrueを返し、そうでなければfalseを返します。 要素Xがすでにセットの中にあれば、そのリストを修正する必要はありません。そうでなければXをリストの最初の要素として追加します。

この例では、パターンマッチはとても単純です。もっと複雑なものもあります。（あなたのコードを [私のコード](http://learnyousomeerlang.com/static/erlang/cases.erl) と比較できます）

``` erlang
beach(Temperature) ->
    case Temperature of
        {celsius, N} when N >= 20, N =< 45 ->
            'favorable';
        {kelvin, N} when N >= 293, N =< 318 ->
            'scientifically favorable';
        {fahrenheit, N} when N >= 68, N =< 113 ->
            'favorable in the US';
        _ ->
            'avoid beach'
    end.
```

これは、「ビーチに行くべき時間か」を摂氏、絶対温度、華氏の3つの温度表現で答えるという関数です。 すべての状況を満たして答えるように、パターンマッチとガードが一緒に使われています。 前に指摘されたように `case ... of` 式は多くの関数の先頭で使われているものと同じです。 実際我々のコードを次のように書くことができます：

``` erlang
beachf({celsius, N}) when N >= 20, N =< 45 ->
    'favorable';
...
beachf(_) ->
    'avoid beach'.
```

ここで疑問が沸き上がってきます：条件式では、いつ `if` を使って、いつ `case ... of` を使って、いつ関数を使えばいいのでしょうか？

## どれを使えばいいの？

どれを使うべきかはわりと答えるのが難しい質問です。関数呼び出しと `case ... of` の違いはとても小さいです。 実際、低レベルの部分では同じように表現されていて、パフォーマンスにおいても甲乙付けがたい状況です。 この2つの1つの違いは、1つ以上の引数が評価される時にあります。 `function(A,B) -> ... end.` はガードと値のパターンマッチがAとBに対して持てますが、case式ではこのように書かなければなりません：

``` erlang
case {A,B} of
    Pattern Guards -> ...
end.
```

この形式はあまり見られず、コードを読んでいる人をちょっと驚かせます。似たような状況では、関数呼び出しを使うほうが適切です。 一方で、ちょっと前に書いた `prepend/2` 関数はほぼ間違い無くcase式を使ったほうが関数呼び出しをして `true`/`false` 節を持つようにするよりすっきりします。

他の疑問として、 `case` や関数のほうがずっと柔軟で、ガードを含め `if` の機能を網羅しているのに、なぜ `if` を使うのか、というのがあります。 これはすべてのパターンを書かなくてもガードをちょっと追加できるように言語に追加しました。

もちろん、これらの全ては個人的な見解で、あなたのほうがこういった状況に多く遭遇するかもしれません。 きっちりした答えはないのです。このトピックは未だにErlangコミュニティで時々議論されています。 誰も、理解しやすい理由があれば、あなたの選択をコケにしたりはしません。 Ward Cunninghamがかつて言ったように、 *「ルーチンを見たときにきれいなコードになっていれば、まさにあなたが期待しているものです」*

