Search code examples
syntaxocamluser-input

Syntax error from ocaml reading standard input


For some reason if I put these functions one by one in utop it works, but if I process them all I got a Syntax error (without anything other insight about what might be wrong).

let rec solve = function
  | [] -> print_string("")
  | a::b -> print_string(a); solve b

let rec read_input acc = function
  | 0 -> acc
  | n -> let s = read_line() in
    read_input (s::acc) (n-1)

let n = read_int() in
let inp = read_input [] n in
solve inp

Solution

  • For me, OCaml points to a syntax error on the first in in the following (I have made formatting a little more conventional):

    let n = read_int() in
    let inp = read_input [] n in
    solve inp;;
    

    Keep in mind that the expression shown above is an expression. Coming where it does after the previous binding causes a syntax error. Let's make it work by making it yet another toplevel binding.

    let rec solve = function
      | [] -> print_string("")
      | a::b -> print_string(a); solve b
    
    let rec read_input acc = function
      | 0 -> acc
      | n -> let s = read_line() in
        read_input (s::acc) (n-1)
    
    let () =
      let n = read_int() in
      let inp = read_input [] n in
      solve inp
    

    As a side note, using the |> operator can make this a bit more concise.

    let () =
      read_int () 
      |> read_input [] 
      |> solve
    

    Also it strikes me than read_input is returning the list in the wrong order:

    utop # read_input [] 2;;
    3
    4
    - : string list = ["4"; "3"]
    

    Maybe you wanted to reverse your accumulator.

    let rec read_input acc = function
      | 0 -> List.rev acc
      | n -> let s = read_line () in
        read_input (s::acc) (n-1)
    

    Or even:

    let read_input n = 
      List.init n (fun _ -> read_line ())