1) Ignore indentation (I intentionally wrote it to deceive, but similar examples could easily appear in real code). 2) `match` cases always bind to the innermost `match` statement. 3) Statement separators (`;`) are tricky.
The correct indentation of the above code is:
if a > 0 then
print_endline "a > 0" ;
match a with
| 0 -> print_endline "impossible"
| 2 ->
match b with
| 0 -> print_endline "2, 0"
| _ -> print_endline "2, not 0"
| 3 -> print_endline "3, something"
| _ -> print_endline "something, something"
;
print_endline "done"
To have the same meaning as the indentation implies, you would need to add `(...)` or `begin ... end` at the appropriate places.
What would be the corresponding SML? I see how the way SML binds ';' would help here, but would it change anything about the last two badly indented matching? And it seems to provide you with the equivalent footgun if you attempt to do multiple side-effect operations in a match branch, which in my experience you want to do more often than you need to separate matches with ';'.
There are two things to remember. The first is the match binding thing that tomp mentions in his reply.
The second one is that in OCaml, semicolon is a separator, and not a terminator. In contrast, in C/C++, semicolon is a terminator. If you have an expression, you end it with a ";" just because.
This is not the case for OCaml. In OCaml, semicolon is used to separate two sequential expressions where only one expression is expected. Thus,
<expr1>;<expr2>
is evaluated in sequence, and can be used in a place where only one is expected. For example, if statements have the following syntax:
if <expr1> then <expr2> else <expr3>
Now if you wanted to do two things (instead of one) in the "then" block, you would simply write
if <expr1> then <expr2.1>;<expr2.2> else <expr3>
Notice that under these rules
if <expr1> then <expr2>; else <expr3>
makes no sense. Separators are not terminators. We are used to thinking of ";" as terminators because of C/C++.
Actually, this will not work, I was also confused by it.
# if true then (); 1 else 2;;
Error: Parse error: [str_item] or ";;" expected (in [top_phrase])
# if true then begin (); 1 end else 2;;
- : int = 1
# if true then ((); 1) else 2;;
- : int = 1
The confusion comes from the fact that it doesn't behave the same way in match expressions:
# match true with | true -> (); 1 | false -> 2;;
- : int = 1
I'll add that you need ';'-as-separator (you also use ';' in other places, such as when separating items in a list) only when calling functions which return 'unit', which is typically functions which perform side-effects (eg, close a file). That's usually a small portion of your program.
The correct indentation of the above code is:
To have the same meaning as the indentation implies, you would need to add `(...)` or `begin ... end` at the appropriate places.