将打印语句放在OCaml代码中

时间:2016-10-25 17:37:23

标签: ocaml

我有以下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

我知道错误可能非常明显,因为它是语法错误,所以我道歉。

我的问题是:如何在代码中放置一些打印语句,以帮助我看到递归调用的参数值?

3 个答案:

答案 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,就可以使用;

作为完全不相关的副评论,firstsecond在OCaml中以fstsnd的名称预定义。

答案 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)
    )
  )
;;