SSブログ

文字ストリームから語のストリームを作る [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 っぽい書き方を習得する必要があるようだ。とりあえず今日はここまで。


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。