OCaml: Pattern matching vs If/else statements

For me if..then..else is equivalent to match .. with | true -> .. | false -> .., but there's a syntax sugar if you are facing cases with nested pattern matching, using if..else in an interlace way can help you avoiding to use begin...end to separate different level of patterns

match .. with
| true -> 
    if .. then 
      match .. with
      | true -> ..
      | false -> ..
    else
      ...
| false -> ...

is more compact than

match .. with
| true ->
   begin 
    match .. with
    | true -> 
       begin
         match .. with
         | true -> ..
         | false -> ..
       end
    | false -> 
      ...
   end
| false -> ...

I don't think there's a clear cut answer to that question. First, the obvious case of pattern matching is when you need destructing, e.g.:

let rec sum = function
    | [] -> 0
    | head :: tail -> head + sum tail;;

Another obvious case is when you're defining a recursive function, pattern matching make the edge condition clearer, e.g.:

let rec factorial = function
    | 0 -> 1
    | n -> n * factorial(n - 1);;

instead of:

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

That might not be a great example, just use your imagination to figure out more complex edge conditions! ;-)

In term of regular (say C like) languages, I could say that you should use pattern matching instead of switch/case and if in place of the ternary operator. For everything else it's kind of a grey zone but pattern matching is usually preferred in the ML family of languages.


As far as I know the signifincant difference is that the expression at the guards in the match statement is a pattern which means you can do things that allow you to break apart the shape (destruct) the matched expression, as Nicolas showed in his answer. The other implication of this is that code like this:

  let s = 1 in
  let x = 2 in 
  match s with
    x -> Printf.printf "x does not equal s!!\n" x
  | _ -> Printf.printf "x = %d\n" x;

won't do what you expect. This is because x in the match statement does not refer to the x in the let statement above it but it's a name of the pattern. In cases like these you'd need to use if statements.