2019/12/12

OCamlのinについて

順番に見るとわかる

OCamlのinは、局所的にスコープを作成するものです。簡単な例を挙げると以下のようなものです。

* let x = 1 in x + 2;;
さて何が返ってくるでしょう?
答えは3です。では以下のような場合はどうなるでしょうか?

* let x = 1 in let x = x + 2 in x + 3;;

答えは6です。見た目が非常にややこしい。いったいどのxがどの値なのか混乱してしまいがちです。
しかし、順番に見ていくとすっきりするはずです。
まず最初の例の説明をすると、最初にxが1に束縛されます。そして次にinがあるので、続きを見てみます。すると、x + 2となっているので、先程束縛されたxと2を加算します。結果3を返すことになります。
同じように2つ目の例を見てみます。
まずxが1に束縛されます。そしてinがあるので続きを見ます。すると、新たにxを束縛しようとしています(まだ束縛されていない)。束縛する値はx + 2となっています。今のところxに束縛されている値は1なので、それを使います。これで新たなxが3に束縛されました。さらにinが付いていますので、続きを見てみます。すると、x + 3となっています。現在xに束縛されている値は3なので、加算すると6になります。
このように順番に考えるとわかりやすくなるように思います。
では以下のようなリストの長さを返す関数の場合を考えてみます。

let length list =
  let rec aux n = function
    | [] -> n
    | _ :: t -> aux (n + 1) t
  in aux 0 list;;
functionは以下の形の省略形になっています。

let length list =
  let rec aux n list =
    match list with
    | [] -> n
    | _ :: t -> aux (n + 1) t
  in aux 0 list;;
順番に考えてみます。
まずlistという引数を持つlengthをいう名前の関数が、nlistを引数に持つ再帰する関数auxに束縛されます。ここでauxも束縛されます。そしてinがついているので続きを見てみます。すると、aux 0 listとなっています。たびたび出てくるlistですが、新たに束縛はしてませんので、その名前は、関数lengthの引数しかありません。したがってそのlistと同じものです。ということで、結果は再帰関数auxの結果となります。

まとめ

言葉で説明するのはなかなか難しいものです。さらに再帰が絡んできたり、もっとネストされていた場合は、より混乱してしまいます。しかし、順番に考えていくとわかりやすくなるのではないかと思います。そして、何度も考えているうちに、自然と身についているということになるやもしれません。ちなみに私はまだまだ……