OCaml: Pattern matching vs If/else statements
Solution 1
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.
Solution 2
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.
Solution 3
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 -> ...
Comments
-
Casey Patton almost 2 years
So, I'm totally new to OCaml and am moving pretty slowly in getting my first functions implemented. One thing I'm having trouble understanding is when to use pattern matching abilities like
let foo = [] -> true | _ -> false;;
vs using the if else structure like
let foo a = if a = [] then true else false;;
When should I use each?
-
Daniel H almost 11 yearsThe accepted answer below seems good in most cases. However, like in most (all?) programming languages, it's rarely a good idea to say something along the lines of
if condition then true else false
; you can instead just usecondition
. In this case, you can saylet foo a = (a = [])
and avoid both pattern matching and if statements.
-
-
Michael Ekstrand over 12 years+1. I'd augment this with one more rule of thumb. If you're pattern-matching against
true
andfalse
, consider anif
. If yourif
uses a function to express a clear pattern-match, considermatch
. Plusmatch
can avoid function calls, unlike manyif
expressions. -
Jeffrey Scofield about 8 yearsFWIW, I don't think
match x with 3 -> f x | _ -> g x
is going to be any more efficient thanif x = 3 then f x else g x
. I would personally concentrate on clarity of the code. -
Neil Philip about 8 yearsIn that case, I would agree. But consider the case,
match x with | 0 -> 1 | 1 -> 2 | 2 -> 3 | _ -> x + 1
vsif x = 0 then 1 else if x = 1 then 2 else if x = 2 then 3 else x + 1
. If you were to benchmark these functions, the pattern matching would be significantly more efficient. As the cases increase (especially when accelerated with recursion), the performance differences can increase by orders of magnitude. -
ELLIOTTCABLE almost 6 yearsI hate to dispense a downvote on SO, but this is actually incorrect — any destructuring in a
let
will behave exactly the same as that same destructuring in amatch
clause.let (hd :: _) = [1; 2; 3]
. (In fact, IIRC,let
-assignment actually desugars to a pattern-match.) -
sashang almost 6 years@ELLIOTTCABLE I think the example I wrote is bad. I meant that something like:
match s with x -> ....
is not the same asif s = x then
. Thex
in the match statement is always going to pattern match withs
. Thex
in theif
statement is testing for equality.