パターンマッチにガード条件を加える [OCaml]
これまでの words の実装ではストリームから Stream.peek で取得した 'a option のヴァリアント型に Some c | None のパターンマッチをして、Some の場合さらにその中身が空白か否かを if を使って条件分岐していた。
「ふつうの Haskell」を読むと Haskell には「ガード」という構文があって、パターンマッチに任意の条件を追加できる。
OCaml にもあるかな?と思って調べたら、あった。以下のように when を使う。
open ExtString.String;;
let stdinstr = Stream.of_channel stdin;;
let words str =
let is_space c = String.contains " \t\r\n" c in
let rec trim_leading charstr =
match (Stream.peek charstr) with
Some c when is_space c -> (Stream.junk charstr; trim_leading charstr)
| Some _ -> charstr
| None -> charstr
in
let rec cut_first_word str =
let c = Stream.next str in
match (Stream.peek str) with
Some next_char when is_space next_char -> c :: []
| Some next_char -> c :: (cut_first_word str)
| None -> c :: []
in
Stream.from (
fun i ->
try
let trimmed = trim_leading str in
Some (implode (cut_first_word trimmed))
with Stream.Failure -> None
)
;;
Stream.iter (Printf.printf "[%s] ") (words stdinstr);;
パターンマッチと if で2階層混在していたのがパターンマッチだけになったのでコードが気持ちすっきりする。
コメント 0