bsky
bsky

Reputation: 20222

Place print statements in OCaml code

I have the following OCaml code (I know it's probably poorly written and complicated but that's beside the point):

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

I want to put a print statement somewhere in the code to see the call stack of findAge.

I tried adding a print statement and I changed the code to this:

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

But I'm getting Error: This '(' might be unmatched.

I know the error is probably quite obvious since it's a syntax error, so I apologize.

My question is: How can I put some print statements in the code that would help me see the value of the parameters for the recursive call?

Upvotes: 0

Views: 2827

Answers (3)

ivg
ivg

Reputation: 35210

There are no statements in OCaml only expressions. Semicolons, that can be used to separate two expressions that evaluate to a value of type unit, usually bring a lot of confusion, because in conventional languages they are used to separate statements. Since there are no statements in OCaml, the if/else is also an expression, so if exp1 then exp2; exp3 is actually parsed as (if exp1 then exp2); (exp3), not as if exp1 then (exp2;exp3), as the if/else syntax is an expression, not a statement, and ; has a lower precedence. You can always try to use parenthesis or begin/else to change the precedence, but for me it is always easier to chain the computations using use let () = exp in ... syntax, that allows me to foget about counting the nestedness of the parenthesis, e.g.,

if exp then 
  let () = debug "woa" in
  ....
  result 
else 
  let () = debug "no way" in
  ...
  another_result

Or, picking your example:

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

Also, a decent OCaml indenter, like ocp-indent can make your life much easier, as it will indent the code in according to OCaml syntax, so you can see what OCaml is getting, not what you is thinking. For example, this is how it will indent your faulty code (actually showing a place where you broke the syntax):

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

Upvotes: 2

V. Michel
V. Michel

Reputation: 1619

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

Upvotes: 0

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66808

You can replace any expression e with a compound expression like this:

(Printf.printf "%d %d\n" (first answer) (second answer) ; e)

In essence, where you have and you can use ;

As a completly irrelevant side comment, first and second are predefined in OCaml under the names fst and snd.

Upvotes: 0

Related Questions