Tambourine作業メモ

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

OCamlでナイーブなtailを作る

プログラミングの基礎 ((Computer Science Library))を読み終わった。それなりに面白かった。正直、赤黒木とかちゃんと理解するのは普通に難しいので飛ばし読みしたけど。昔、一度理解はしたけど、実装しろと言われたらもう一度勉強し直さないとどうにもならないだろうなあ。

さて、OCamlをざっと理解した気になったので、Goと同じプログラムをOCamlで作ってみることにしよう。先ずは、tailが作れないことには話にならない。

とはいえ、教科書にファイルの読み書きは出てこないのだった(笑)。副作用のある処理はオマケ扱いだ。

標準出力への書込が出来ないと何が正しいのかさっぱりわからないので、Hello Worldから行こう。

> cat tail.ml
let () = print_endline "Hello, OCaml!"
> ocamlopt -o my_tail tail.ml 
> ./my_tail 
Hello, OCaml!

ocamloptコマンドは、ネイティブバイナリを作ってくれる。

さて、ファイルを読み込んでみよう。コマンドライン引数の処理方法をまだ知らないので、読み込むファイルは固定にする。

open_inでファイルを開き、input_lineで読む。 EOFまで読むと例外になるので、それをキャッチして読込を止める。とても命令型な処理になる。 教科書が何にも役に立たない(笑)。

let fi = open_in "./sample.memo"

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

let () = List.iter print_endline lines

whileを使ってファイルを読むところは、mutableなlstやモードを持つeofが出てきて全然functionalじゃない。がっかりだ。

とりあえず、これでcatコマンド相当だ。

tailにするには、listの後ろを取り出す。実は後ろを取り出すのは、再帰だと簡単だ。 こんな関数で出来る。

let n = 5
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 

これで後ろの5行が取り出せることになる。