Enrico Borba
Enrico Borba

Reputation: 2127

OCaml Syntax Error fixed by double semicolon

I'm sorry for asking such a basic question here, but I'm getting a syntax error when trying to compile the following code,

let sum_of_squares_of_two_largest x y z =
    let a :: b :: _ = List.sort (fun x y -> -(compare x y)) [x; y; z] in
    a * a + b * b;

let rec factorial n =
    if n = 0 then 1 else n * factorial (n - 1);

let e_term n = 1.0 /. float_of_int (factorial n);

let rec e_approximation n =
    if n = 0 then (e_term 0) else (e_term n) +. (e_approximation (n - 1));

let rec is_even x = if x = 0 then true else is_odd (x - 1);
    and is_odd  x = not (is_even x);

let rec f_rec n =
    if n < 3 then n else f_rec(n - 1) + 2 * f_rec(n - 2) + 3 * f_rec(n - 3);

The uninformative compiler tells me there is syntax error on line 19, which is the last line of the file.

File "source.ml", line 19, characters 0-0:
Error: Syntax error

That is, line 19 is a blank line, only with a new-line character.

I can "fix" this syntax error by adding ;; at the end of each function definition instead of the ;.

Am I missing a semicolon somewhere?

Upvotes: 2

Views: 1836

Answers (1)

glennsl
glennsl

Reputation: 29106

As has been pointed out in the comments, ; is not a statement terminator like in many other (Algol-inspired) languages, but a sequence operator. It takes two values, throws away the first (but warns if it is not unit) and returns the second. a; b is therefore roughly equivalent to let _ = a in b.

You say you would have expected the error to say something like ';' is missing the second operand., but the thing is: it doesn't. Not until it reaches the end of the file (at which point the error message certainly could have been more intelligent, but probably not very accurate anyway).

What follows each ; in your code looks like a perfectly valid expression that might yield a value. For example, if let rec factorial n = ...; had been let rec factorial n = ... in 2 The value of the expression would have been 2. The problem here, from the compiler's point of view, is that it runs out of file before the expression is finished.

As you've also found out, ;; actually is a statement terminator. Or perhaps a toplevel definition terminator is a better term (I don't know if it even has an official name). It's used in the REPL to terminate input, but isn't needed in normal OCaml code unless you mix toplevel definitions and expressions, which you never should.

;; can still be useful for beginners as a "bulkhead", however. If you put just one ;; in place of a ; in the middle of your file, you'll find the compiler now points the error location there. That's because ;; terminates the definition without the preceding expression being complete. So you now know there's an error before that. (Actually in the preceding expression, but since your entire file is one single expression, "before that" is really the best we can do).

Upvotes: 5

Related Questions