16章 データフォーマッティング

16.2

空白区切りの文字列を読み込んで整数を返す関数を作る.
以下動作の様子

- val f = readInt "123 345 abc";
- f (); (* 呼び出す毎に *)
val it = SOME 123 : int option
- f (); (* 整数を切り出す *)
val it = SOME 345 : int option
- f ();
val it = NONE : int option

実装(回答)

val insScan = Int.scan StringCvt.DEC Substring.getc;
fun readInt (s:string) : unit -> int option =
  let
    val rs = ref $ Substring.full s
    fun readImpl () = (case intScan (!rs) of
           SOME (f,sub) => (rs := sub; SOME f)
         | NONE         => (rs := Substring.full ""; NONE))
  in
    readImpl
  end

16.3 readReal, readBoolを作る

めんどいのでReal版だけ :p

fun readReal s =
let
  val rs = ref $ Substring.full s
  fun readImpl () = (case Real.scan Substring.getc (!rs) of
                          SOME (f,sub) => (rs := sub; SOME f)
                        | NONE         => (rs := Substring.full ""; NONE))
in
  readImpl
end

16.4 genericReadInt

charを読み出すreaderからintを読み出す関数.

fun genericReadInt (reader : (char,'a) StringCvt.reader) (x : 'a) : unit -> int option =
let
  val rx = ref x
  fun greader () = (case Int.scan StringCvt.DEC reader $ (!rx) of
                         SOME (f,rest) => (rx := rest; SOME f)
                       | NONE          => NONE)
in
  greader
end

16.5

入力ストリームを受け取ってintを読み出す.

fun readIntFromStream (st : TextIO.instream) : unit -> int option =
let
  (* ストリームreaderをでっち上げる *)
  fun reader s = case TextIO.input1 s of
                      SOME c => SOME (c,s)
                    | NONE   => NONE
  val streader : unit -> int option = genericReadInt reader st
in
  streader
end

16.5.2

ファイルからテキストを読み込んで整数リストを返す

fun readIntFromFile (path : string) : int list =
let
  val sread : unit -> int option = readIntFromStream $ TextIO.openIn path
  fun readtoken () = case sread () of
                       SOME x => x::(readtoken())
                     | NONE   => []
in
  readtoken ()
end

まとめ

  • この本の中で使われている Substring.all はSML/NJには見あたらない.

代わりに Substring.full を使ってある.

  • 読み込む関数に状態持たせるのはあんまりいい手じゃないような.
  • アノテーションが書きにくい&読みにくい. 関数と型構築子はデータの前に付けるのに, 高階型の名前は後ろに付いていくのは直感に反するです. (int option listとか)


SML書いてたら楽しくなってきたので律儀に問題解いてしまう….