Reputation: 495
Haven't been able to find much online documentation regarding begin/end in ocaml. I have two different pattern matches in the same function (which I want to be independent of each other), but vscode is parsing them to nest the second inside the first. I've tried surrounding the first pattern match in begin/end, but it's giving me syntax errors:
begin match c.r with (* first pattern match *)
| [ r1; r2; r3 ] ->
let _ = print_endline (String.make 1 r3.top) in end
match cl with (* second pattern match *)
| [] -> []
I get a red underline on end
that says Syntax error after unclosed begin, expecting expr
. I do not understand what this means, since I wrote end
to close the begin
, so why is the begin
unclosed? The code compiles fine without the begin/end (except that it nests the second pattern match inside the first one). Thanks.
Upvotes: 1
Views: 1752
Reputation: 36620
What Jeffrey Scofield said. Consider how this can become confusing when we nest matches. How do we read the following?
match "foo" with
| "bar" -> 42
| "foo" ->
match "baz" with
| "baz" -> 27
| _ -> 19
| _ -> 33
The indentation makes it fairly clear what the programmer meant, but OCaml doesn't care about your pretty indentation. It could just as easily be that you meant:
match "foo" with
| "bar" -> 42
| "foo" ->
match "baz" with
| "baz" -> 27
| _ -> 19
| _ -> 33
Or:
match "foo" with
| "bar" -> 42
| "foo" ->
match "baz" with
| "baz" -> 27
| _ -> 19
| _ -> 33
Either parentheses or begin/end disambiguate this situation.
match "foo" with
| "bar" -> 42
| "foo" ->
(match "baz" with
| "baz" -> 27
| _ -> 19)
| _ -> 33
Or:
match "foo" with
| "bar" -> 42
| "foo" ->
begin
match "baz" with
| "baz" -> 27
| _ -> 19
end
| _ -> 33
Nested match
expressions are often unnecessary. Consider when you have a nested match
if you can't more cleanly express the same as a single level match
on a tuple of values.
match a with
| X -> ...
| Y ->
(match b with
| Z -> ...
| W -> ...
| _ -> ...)
| U ->
(match c with
| F -> ...
| G -> ...
| _ -> ...)
| _ -> ...
vs.
match a, b, c with
| X, _, _ -> ...
| Y, Z, _ -> ...
| Y, W, _ -> ...
| Y, _, _ -> ...
| U, _, F -> ...
| U, _, G -> ...
| U, _, _ -> ...
| _, _, _ -> ...
Note that the number of outcomes remains eight in either case.
Naturally this doesn't work if the inner match is against a computation on the value which would not otherwise need to occur or could not occur in other cases.
Upvotes: 3
Reputation: 66823
In OCaml begin/end
is essentially identical to open/close parentheses. Inside you should have a well-formed expression (as in pretty much any programming language).
What you have inside your begin/end
is not an expression, since it ends with in
. A let
expression looks like let pattern = expr1 in expr2
. You are missing the second expression inside the begin/end
.
What you should do (I think) is put begin/end
around the inner match
like this:
match c.r with
| [r1; r2; r3 ] ->
let _ = print_endline (String.make 1 r3.top) in
begin
match c1 with
| [] -> []
...
end
| ...
(This code doesn't make a lot of sense but I assume it's just an example.)
As another simplification you can change let _ = a in b
to a; b
if a
is of unit type, as it is in your code.
Upvotes: 5