是否可以在代码块中放置用于调试/测试的print语句?例如,在Java中,您可以在方法中间使用System.out.println("")
来检查变量或其他内容,但在OCaml中,print_string
之类的命令是否有效?它不会返回类型单位的值,从而导致错误,而不是允许您打印它吗?
答案 0 :(得分:21)
如果您将打印件嵌入expression sequence。
,则可以<强>更新强>
这是一个具体的例子,因为上面的答案相当短,而且,只有链接的答案才是好的答案。它是阶乘的经典尾递归公式(是的,无聊的,但很熟悉):
# 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.
答案 1 :(得分:12)
由于OCaml不是纯函数式语言,因此有很多方法可以做到这一点。这是我编写这种代码的方式,只是为了一个具体的例子。
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
进行大量调试(就像我一样),了解这一点非常有用。
答案 2 :(得分:4)
这是一个简单的例子,表明Ray Toal's answer中提到的表达序列不一定需要围绕它们的括号:
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");