Reputation: 2015
I am following this draw_string_in_box example in Developing Applications with OCaml
The sample code given is as follows:
let draw_string_in_box pos str bcf col =
let (w, h) = Graphics.text_size str in
let ty = bcf.y + (bcf.h-h)/2 in
( match pos with
Center -> Graphics.moveto (bcf.x + (bcf.w-w)/2) ty
| Right -> let tx = bcf.x + bcf.w - w - bcf.bw - 1 in
Graphics.moveto tx ty
| Left -> let tx = bcf.x + bcf.bw + 1 in Graphics.moveto tx ty );
Graphics.set_color col;
Graphics.draw_string str;;
If I remove the parentheses around the "match" part, the code won't work (nothing gets printed). Any idea why?
And more generally, when should I put parenthese around code bits like this?
Thanks.
Upvotes: 2
Views: 505
Reputation: 4405
As explained by Jeffrey, if you remove the parentheses then the Graphics.set_color col; Graphics.draw_string str
statements are understood to be part of the | Left ->
case.
This answer is more about when to use parentheses in such code excerpts. In a majority of situations, a pattern matching is the last expression of a function, e.g.:
let f x y =
foo x;
match y with
| Bar -> Printf.printf "Found y=Bar!\n%!"; 42
| Baz -> Printf.printf "Found y=Baz!\n%!"; 43
And in this case you do not need parentheses. Quite often, it is also the first, and thus the only expression of the function:
let hd list = match list with
| a :: _ -> a
| [] -> invalid_arg "hd"
But when you want to do things after the matching, you need to tell OCaml where the matching ends. This is where you use parentheses:
let f x y =
foo x;
(match y with
| Bar -> 42
| Baz -> 43);
(* do something, both when y is Bar and when it is Baz: *)
qux x y;
The same applies to try ... with
statements:
let find_a_b a b list =
(try print_int List.assoc a list
with Not_found -> Printf.printf "Could not find a=%s.\n%!" a);
(* Now do something whether or not we found a: *)
(try print_int List.assoc b list
with Not_found -> Printf.printf "Could not find b=%s.\n%!" b);
Here the first parentheses are mandatory, the seconds are optional, and usually not written.
Upvotes: 3
Reputation: 66808
One way to look at it is that after the arrow ->
of a match
statement you can have a sequence of expressions (separated by ;
). Without the parentheses, the following expressions look like they're part of the last case of the match
.
You can also have a sequence of expressions (separated by ;
) after let
. With the parentheses, the following expressions look like they're part of the let
, which is what you want.
Personally I avoid using ;
. That's how I deal with this problem! Otherwise you have to figure the expression sequence goes with the innermost construct that takes a sequence.
Upvotes: 5