文字ストリームから語のストリームを作る [OCaml]
「ふつうのHaskell」によると Haskell には words 関数というのがあってこういうふうに使うらしい。
Prelude> words "This is a pen"
["This","is","a","pen"]
OCaml には似たような関数はないようなのでこれを作ってみる。
Haskell の words は「文字列 -> 文字列のリスト」だけど、「ストリーム -> ストリーム」で作ってみた。
以下の words のストリームビルダーの関数は呼ばれるとまずストリームの最初の空白を除去して最初の一語を切り出して返す。
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 ->
if is_space c then
(Stream.junk charstr; trim_leading charstr)
else
charstr
| None -> charstr
in
let rec cut_first_word str =
let c = Stream.next str in
match (Stream.peek str) with
Some c2 ->
if is_space c2 then
String.make 1 c
else
String.concat "" [(String.make 1 c); (cut_first_word str)]
| None -> String.make 1 c
in
Stream.from (
fun i ->
try
let trimmed = trim_leading str in
Some (cut_first_word trimmed)
with Stream.Failure -> None
)
;;
Stream.iter (Printf.printf "[%s] ") (words stdinstr);;
作っては見たけどかなりいまいち。
trim_leading はリストを扱うみたいな書き方で Stream を返すけどそもそも Stream は状態を持つから let trimmed = trim_leading str in Some (cut_first_word trimmed)
じゃなくて trim_leading str; Some (cut_first_word str)
と書いても同じことになる。あまり意味ないかな。
cut_first_word も何かもっとうまい書き方があるような気がする。もうちょっと OCaml のコードを読んで OCaml っぽい書き方を習得する必要があるようだ。とりあえず今日はここまで。
コメント 0