Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

OCamlでコマンドライン引数を処理する

さて、次はファイル名や表示行数を指定できるように修正しよう。

引数は、Cのargv相当がSys.argvに入ってくるが、自分でパースするのはめんどうだ。 もちろん、標準ライブラリでパースできる。Argモジュールを使う。

以下の手順を踏む。

  1. 引数で指定された情報を格納する参照を定義する
  2. どんな引数がくるのか、定義を作る
  3. パースする

詳しいことは、 http://caml.inria.fr/pub/docs/manual-ocaml/libref/Arg.html を読む。 手順2のanon_funに何を指定するのかわかりにくいが、要するにフラグ無しの引数の扱いを指定すればいい。

tail -n 5 filename に対応したかったら、

let n = ref 5 (* 表示する行数 *)
let inputfile = ref ""

let spec = [("-n", Arg.Set_int n, "Number of lines")]
let () = Arg.parse spec (fun s -> inputfile := s) ""


(* ファイルを全行読み込む *)
let fi = open_in !inputfile

let lines = 
  let lst = ref [] in
  let eof = ref false in 
  while not !eof do
    try lst := !lst @ [(input_line fi)] with End_of_file -> eof := true
  done;
  !lst

let () = close_in fi


(* 行のリストの最後n行だけ取り出す*)
let rec tail lst = match lst with
    [] -> [] 
  | first :: rest -> 
    let last = tail rest in
    if List.length last > !n - 1  then last else first :: last 

let () = List.iter print_endline (tail lines)

これでOK。以外とバリバリrefを使うのである(笑)。