18734


OCaml 4.01.0で、標準入力から

A1 A2 A3 ... An

というように任意個数のint型の引数をスペース区切りで与え、これに関数を適用したいのですが  
いい方法が浮かびません・・・

具体的には引数たちを配列とかリストにして関数を適用したいと思っています。  
Scanfなどでうまくできないか、  
<http://caml.inria.fr/pub/docs/manual-ocaml/libref/Scanf.html>  
で探したところ、  
%sでスペース区切りまでの文字列を読み込めること  
%Nまたは%Lでいままでに読み込んだtokenの個数を返すこと  
などはわかったのですが、読み込むtokenの個数を指定する方法や、入力の途中から読み込みを  
再開する方法などがわからず、うまく使えません。  
一応、標準入力をまるごと文字列として、区切りごとに切り取ってintに変換しリストに入れていくという  
方法でなんとか動かすことができたのですが、何とも回りくどく感じています。

どんなものでも構いませんので、標準入力からうまく任意個数の引数を読み込む方法はないでしょうか？？  
入力の形は上記のスペース区切りのままでよろしくお願いします。


CC BY-SA 3.0
2015-11-12T09:45:43.727
18732
2015-11-12T11:05:31.530
13240
question
ocaml
任意個数の引数の読み込み


「標準ライブラリ」しか使えないという場合は、たとえば、自分で

[code]

    val split : string -> char -> string list
    
[/code]

という分割関数を書いた後、

[code]

    List.map int_of_string @@ split s ' '
    
[/code]

のが普通です。このような関数が「標準ライブラリ」に存在しないので仕方ありません。

OCaml コンパイラ自身のソースコードでもこういった分割関数が定義されています。こんなコードです:

[code]

    (* split a string [s] at every char [c], and return the list of sub-strings *)
    let split s c =
      let len = String.length s in
      let rec iter pos to_rev =
        if pos = len then List.rev ("" :: to_rev) else
          match try
                  Some ( String.index_from s pos c )
            with Not_found -> None
          with
              Some pos2 ->
                if pos2 = pos then iter (pos+1) ("" :: to_rev) else
                  iter (pos2+1) ((String.sub s pos (pos2-pos)) :: to_rev)
            | None -> List.rev ( String.sub s pos (len-pos) :: to_rev )
      in
      iter 0 []
    
[/code]

これが「標準ライブラリ」に移ってくれると助かるのですが、されません。文字列の分割というと単に一つの文字で区切るだけでなく、複数の文字をデリミタにしたい、エスケープされているデリミタでは分割したくない、など、いろんな仕様が考えられ、それぞれに最適な実装も異なります。こういう場合、
OCaml では「標準ライブラリ」では提供しない、自分でライブラリモジュールを書いてくれ、ということが多いみたいです。

外部ライブラリを使える場合は

  * Str の `Str.split` (正規表現を使うので空白分割ごときに使うのはあまりよくないと思います
  * Core の `Core.Std.String.split_on_chars : string -> on:char list -> string list`
  * Batteries の `BatString.nsplit : string -> by:string -> string list`
  * Extlib の `ExtLib.String.nsplit : string -> string -> string list`

などがあるので、これらを使うのが良いです。


CC BY-SA 3.0
2015-11-12T10:59:26.080
18734
2015-11-12T11:05:31.530
2015-11-12T11:05:31.530
898
898
18732
answer