我有以下OCaml代码(我知道它可能编写得很糟糕而且很复杂,但这不是重点):
let first (a, _) = a
let second (_, b) = b
let rec findAge limits answer : (int * int) =
if not(first(limits) <= first(answer) &&
first(answer) < second(answer) &&
second(answer) <= second(limits))
then (0, 0)
else
let x = is_valid_answer(answer)
in if x = true
then answer
else
(let y = findAge limits (first(answer) - 1, second(answer))
in if y != (0, 0)
then y
else findAge limits (first(answer), second(answer) - 1));;
我想在代码中的某处放置一个print语句来查看findAge
的调用堆栈。
我尝试添加print语句,然后将代码更改为:
let rec findAge limits answer : (int * int) =
if not(first(limits) <= first(answer) &&
first(answer) < second(answer) &&
second(answer) <= second(limits))
then (0, 0)
else
(Printf.printf answer and
let x = is_valid_answer(answer)
in if x = true
then answer
else
(let y = findAge limits (first(answer) - 1, second(answer))
in if y != (0, 0)
then y
else findAge limits (first(answer), second(answer) - 1)));;
但我得到了Error: This '(' might be unmatched
。
我知道错误可能非常明显,因为它是语法错误,所以我道歉。
我的问题是:如何在代码中放置一些打印语句,以帮助我看到递归调用的参数值?
答案 0 :(得分:1)
仅OCaml表达式中没有语句。分号可用于分隔两个表达式,这两个表达式求值为单位类型的值,通常会带来很多混淆,因为在传统语言中它们用于分隔语句。由于OCaml中没有语句,if/else
也是一个表达式,因此if exp1 then exp2; exp3
实际上被解析为(if exp1 then exp2); (exp3)
,不是被解析为if exp1 then (exp2;exp3)
,因为if/else
语法是表达式而不是语句,;
具有较低的优先级。您总是可以尝试使用括号或begin/else
来更改优先级,但对我来说,使用let () = exp in ...
语法链接计算总是更容易,这使我可以很容易地计算括号的嵌套性,例如,
if exp then
let () = debug "woa" in
....
result
else
let () = debug "no way" in
...
another_result
或者,选择你的榜样:
open Printf
let rec findAge limits answer : (int * int) =
if not(first(limits) <= first(answer) &&
first(answer) < second(answer) &&
second(answer) <= second(limits))
then (0, 0)
else
let () = printf "here I will print the answer" in
let x = is_valid_answer(answer)
in if x = true
then answer
else
(let y = findAge limits (first(answer) - 1, second(answer))
in if y != (0, 0)
then y
else findAge limits (first(answer), second(answer) - 1));;
另外,一个像ocp-indent
这样的OCaml压头可以让你的生活更轻松,因为它会根据OCaml语法缩进代码,这样你就可以看到OCaml得到的东西,而不是你在想什么。例如,这就是它如何缩进你的错误代码(实际上显示了你破坏语法的地方):
let rec findAge limits answer : (int * int) =
if not(first(limits) <= first(answer) &&
first(answer) < second(answer) &&
second(answer) <= second(limits))
then (0, 0)
else
(Printf.printf answer and
let x = is_valid_answer(answer)
in if x = true
then answer
else
(let y = findAge limits (first(answer) - 1, second(answer))
in if y != (0, 0)
then y
else findAge limits (first(answer), second(answer) - 1)));
答案 1 :(得分:0)
您可以使用如下复合表达式替换任何表达式e
:
(Printf.printf "%d %d\n" (first answer) (second answer) ; e)
从本质上讲,只要你有and
,就可以使用;
作为完全不相关的副评论,first
和second
在OCaml中以fst
和snd
的名称预定义。
答案 2 :(得分:0)
let rec findAge limits answer : (int * int) =
if not(fst(limits) <= fst(answer) &&
fst(answer) < snd(answer) &&
snd(answer) <= snd(limits))
then (0, 0)
else (
Printf.printf "(%d,%d)" (fst answer) (snd answer);
let x = is_valid_answer(answer) in
if x = true
then answer
else (
let y = findAge limits (fst(answer) - 1, snd(answer)) in
if y <> (0, 0)
then y
else findAge limits (fst(answer), snd(answer) - 1)
)
)
;;