web-dev-qa-db-ja.com

OCaml Printステートメント

コードのブロックにデバッグ/テスト用の印刷ステートメントを置くことは可能ですか?たとえば、Javaでは、メソッドの途中でSystem.out.println("")を使用して変数などをチェックできますが、OCamlではprint_string仕事?それはあなたがそれを印刷することを許可する代わりに、ユニットタイプの値を返し、それゆえエラーを引き起こしませんか?

14
dxu

印刷物を 式シーケンス に埋め込むと問題ありません。

[〜#〜]更新[〜#〜]

上記の答えがかなり短かったので、具体的な例を示します。リンクだけの答えは良い答えではありません。これは、階乗の古典的な末尾再帰的定式化です(うん、退屈ですが、おなじみです)。

# let fac n =
  let rec f i n acc =
    if i >= n
    then acc
    else (Printf.printf "%8d%8d%8d\n" i n acc; f (i+1) n ((i+1)*acc))
  in
    f 0 n 1;;
val fac : int -> int = <fun>
# fac 5;;
       0       5       1
       1       5       1
       2       5       2
       3       5       6
       4       5      24
- : int = 120

ここでは、印刷の副作用を確認できますが、結果は予想どおり120であることが判明しました。

21
Ray Toal

OCamlはpure関数型言語ではないため、これを行うには多くの方法があります。具体的な例として、私がこの種のコードを書く方法を以下に示します。

let rec mylength list =
(* DEBUG *)
let () = Printf.printf "mylength here, null list: %b\n%!" (list = [])
in
(* DEBUG *)
    match list with
    | [] -> 0
    | _ :: rest -> 1 + mylength rest

動作したら、(* DEBUG *)コメント内の内容を削除できます。

%!の使用に注意してください。バッファをフラッシュします。 (私と同じように)printfを使用して多くのデバッグを行う場合、これについて学ぶことは本当に役に立ちます。

12

Ray Toalの回答 で説明されている式シーケンスは必ずしも括弧で囲む必要がないことを示す簡単な例を次に示します。

let get_a_string = 
  let a_string = "a string" in
  (* The semicolon causes the return value of the statement to be discarded *)
  Printf.printf "Debug: %s\n" a_string; 
  a_string

let () = Printf.printf "Result: %s\n" get_a_string

関数の戻り値を破棄する別の方法は、ignoreを使用することです。

ignore (Printf.printf "Debug info");
4
Matthias Braun