32.7 ソースファイルの作成と読み込み

大きなプログラムを作る場合には,テキストエディタなどを使ってソースコードを書いたファイル(ソースファイル)をあらかじめ作成しておきます.変数や関数の定義を1つ1つキーボードから入力するかわりに,そのファイルを読み込ませて作っておいたプログラムを後からいつでも使うことができるようになります.
OCamlインタープリタには,ファイルとして用意したソースコードをあたかもキーボードから入力されたかのごとく読み込む機能がありますので,その手順を説明します.

ソースファイルの作成

ソースファイルを作るには,テキストエディタを使ってテキスト形式のファイルに変数や関数の定義を書きます.OCamlではソースファイルには“.ml”で終わるファイル名を付けるという約束がありますので,ここでは“quadratic.ml”という名前のファイルを作ることにしましょう.
ファイルの中には,これまでキーボードから入力した,変数や関数の定義を順に書くだけです.定義を書いた順番に注意して定義を集めると,次のようになります.キーボードから入力していたときは入力の最後を示すのに“;;”を付けていましたが,ファイルの中に書く必要はありません.

(* quadratic.ml: 2次方程式 ax^2 + bx + c = 0 *)
(* 自乗 *)
let square(x) = x *. x
(* 判別式 *)
let discriminant(a, b, c) = square(b) -. 4.0 *. a *. c
(* 解の公式 *)
let quadratic1(a, b, c) = (-. b +. sqrt(discriminant(a,b,c))) /. (2.0 *. a)
let quadratic2(a, b, c) = (-. b -. sqrt(discriminant(a,b,c))) /. (2.0 *. a)

ここで“(*”と“*)”で囲まれた部分は注釈であり,OCamlは読み飛ばすので,プログラムとしては何も書いていないのと同じことです.後からプログラムを見たときに,どこで何をやっているかが分かるようにこまめに注釈を書いておきましょう.なお,“(*”と“*)”にいわゆる全角文字を使うと,エラーになりますので注意して下さい.
また,変数や関数を使う場合は,必ず定義が先にあることに気付いたでしょうか.OCamlでは,キーボードから入力するときだけでなくソースファイルを書く場合でも,定義を先に書かなければいけません.

ソースファイルの読み込み

ではキーボードからの入力のかわりに,ファイルから変数や関数の定義を読み込んでみましょう.
OCamlインタープリタでソースファイルから定義を読み込むには,

#use "ファイル名";;

と入力します.
本当にファイルから読み込んだことが分かるように,以下では

  1. 一度OCamlインタープリタを終了して,
  2. “quadratic.ml”というファイルがあることを確認し,
  3. もう一度OCamlインタープリタを起動して,
  4. 最初は“quadratic1”という関数が無いことを確め,
  5. “quadratic.ml”から定義を読み込み,
  6. 関数“quadratic1”を使ってみます.

#quit;;return2
(* ocaml処理系を終了します *)
ls quadratic.mlreturn2
(* quadratic.mlというファイルがあることを確認します *) quadratic.ml (* このように表示されればOKです *)
ocamlreturn2
(* OCamlインタープリタを再度起動します *) Objective Caml version 3.12.1
quadratic1(1.0, 2.0, 1.0);;return2
(* quadratic1という関数を使おうとすると… *) Error: Unbound value quadratic1 (* そのような関数は無いというエラーになります *)
#use "quadratic.ml";;return2
(* quadratic.mlから定義を読み込みます *) val square : float -> float = <fun> val discriminant : float * float * float -> float = <fun> val quadratic1 : float * float * float -> float = <fun> val quadratic2 : float * float * float -> float = <fun>
quadratic1(1.0, 2.0, 1.0);;return2
(* もう一度quadratic1を使おうとすると… *) - : float = -1. (* 今度は計算ができました *)

これで関数が多いときも心配なくなりましたね.