OCaml プログラミング入門


「○○がしたい時はどうする?」集

ここでは、やりたい目的があった時にそれをどうやるのか、 という事例をまとめていきたいと思います。

ファイルを行単位で処理する

Perl などで簡単にできるような、ファイルを一行単位に読んで、 各行になんらかの処理をしたい時はどうするのが良いでしょう。 自分で再帰的な関数を作ってももちろん良いのですが、 Stream を使うと便利です。

let make_stream filename = 
  let ich = open_in filename
  Stream.from (fun i -> try Some (input_line ich) with End_of_file -> close_in ich; None)

make_stream filename は、ファイル: filename の一行ずつが要素と なったストリーム (string Stream.t) を作ります。 ストリームは「遅延リスト」みたいなもので、次の要素は何か? と聞いた時点で初めて次の要素を求めるための計算が行なわれます (上の場合は (fun i -> ...) がそう)。 あとは、

Stream.iter (fun l -> l に対してなんらかの処理) (make_stream filename)

とすれば、ファイル: filename の一行ずつが、真中の引数 の関数に渡されて、処理する事ができます。 ただ、リストとは違って、ストリームは状態を持つので注意して下さい (「次の」の基準となる位置が状態と言う事になります)

例: ファイルに一行ずつ行番号を付加して表示する

Stream.iter
  (let lineno = ref 0 in
      fun l -> incr lineno; Printf.printf "%d: %s\n" !lineno l)
  (make_stream filename)