「プログラミングの基礎」読みほぐし④
上記記事の続きです。
4.3 関数の型
Ocaml は強く型付けされており、プログラム中で出てくるデータのすべてにデータ型がついています。
この性質は関数にも適用されます。関数にもすべて型がついているのです。
例えば、次の関数を定義した際のインタプリタの返答を見ていきましょう。
# let f x = 3 * x ;; val f : int -> int = <fun> // f というint -> int 型の関数を定義しました。その値は関数です。 //(という意味)
この例で言うと、関数の型は「int -> int 型」となります。
関数の型は、A -> B のように書き、これで「A型の値を受け取ったらB型の値を返すような関数の型」を表します。
引数が2つ以上ある次のような場合はどうでしょう。
# let g x y = x * x + y * y - 4 ;; val g : int -> int -> int = <fun>
引数が x と y と、2つあります。
この場合、関数 g は 「int -> int -> int 型」の関数となり、A -> B -> C すなわち「ひとつ目の引数としてA型の値を受け取り、ふたつ目の引数としてB型の値を受け取る。結果、C型の値を返す関数。」となります。
ちなみに、 = <fun>
の
4.4 型推論と型チェック
Ocaml インタプリタは、ぼくらの見えないところで以下の2つのことを行ってくれています。
- 型推論
- 型チェック
型推論
関数を定義した際に、式で使用されている値をもとに関数の型を決めることをいいます。
型チェック
期待される正しい型のデータが使われているかチェックすることをいいます。
強く型付けされた言語では、この型チェックによってプログラムの信頼性を大きく向上させることができるようですね。
現レベルではそのようなメリットを享受できないかもしれませんが、自分でプログラムを作るようになると、そのありがたさを痛感するようになるようです。
4.5 関数の実行方法
変数を使ったプログラムがどのように実行されるかは、前々回くらいに見ていきましたが、関数は引数があるため多少複雑になります。
さて、実際に例を見ていきましょう。
# let jikyu = 950 ;; val jikyu : int = 950 # let kihonkyu = 100 ;; val kihonkyu : int = 100 # let kyuyo x = kihonkyu + x * jikyu ;; val kyuyo : int -> int = <fun> #
上記の宣言をしたあとに、次の計算を実行したとします。
# kyuyo 25 + kyuyo 28 + kyuyo 31
まず、Ocaml インタプリタは kyuyo 25
を実行しようとします。ここで、一発目の関数呼び出しが行われます。
関数が呼び出されたときは次の2つのことが行われます。
- 関数呼び出しを呼びだされた関数の中身で置き換える
- 置き換えられた関数の中身のうち、引数を実引数で置き換える
ここでいう、実引数とは、関数呼び出しをしたときに渡された値のことです。 たとえば kyuyo 25
という関数呼び出しでは実引数は 25 となります。
その後は次のように実行されます。
(kihonkyu + x * jikyu) + kyuyo 28 + kyuyo 31 // 関数が置き換わる (kihonkyu + 25 * jikyu) + kyuyo 28 + kyuyo 31 // x が実引数に置き換わる (100 + 25 * jikyu) + kyuyo 28 + kyuyo 31 // 変数の実行過程と同様 (100 + 25 * 950) + kyuyo 28 + kyuyo 31 (100 + 23750) + kyuyo 28 + kyuyo 31 23850 + kyuyo 28 + kyuyo 31 // 2度目の関数呼び出し 23850 + (kihonkyu + 28 * jikyu) + kyuyo 31 23850 + (100 + 28 * jikyu) + kyuyo 31 23850 + (100 + 28 * 950) + kyuyo 31 23850 + (100 + 26600) + kyuyo 31 23850 + 26700 + kyuyo 31 50550 + kyuyo 31 // 3度目の関数呼び出し 50550 + (kihonkyu + 31 * jikyu) 50550 + (100 + 31 * jikyu) 50550 + (100 + 31 * 950) 50550 + (100 + 29450) 50550 + 29550 80100 // 解
このように、Ocaml の関数は非常に数学の関数と近しいものとなっています。 数学の関数ってなんでしたっけ?
ちなみに、C などの命令形プログラミング言語にも関数という概念がありますが、それと Ocaml の関数ではまったくの別物となります。
続く
続きます。ハァ、ハァ・・・
次回は 4.6 関数定義に対するデザインレシピ をじっくり見ていきたいと思います。
それでは。