"It's hard to know exactly how useful this is in practice, since I've never had cause to write mutually recursive functions, nor have I been able to think of a non-trivial example. However it's there."
It's not there just because it's fancy. If you need a non-trivial exemple, here is one.
1. We have the long multiplication product which is faster for small integers (say less than 1000 digits) but slower for bigger integers.
let long_mult_big (a: big_int) (b: big_int) =
let i = ref 0
and j = ref (Array.length b-1) in
let result = shift_big (scale_up_big a b.(!i)) !j
in begin
while !j > 0 do
incr i; decr j;
let _ = add_big result (shift_big (scale_up_big a b.(!i)) !j)
in ();
done;
result
end;;
2. We have the Karatsuba product wich is faster than "long_mult_big" for integers bigger than say 1000 digits.
3. We want "mult_big", a general product that offers best performance regardless integer size, we implement it using mutual recursion:
let karatsuba_threshold = 1000;;
let rec mult_big (a: big_int) (b: big_int) =
if Array.length a < Array.length b then
mult_big b a
else if Array.length b < karatsuba_threshold then
long_mult_big a b
else
karatsuba_mult_big a b
and karatsuba_mult_big (p: big_int) (q: big_int) =
assert (Array.length p >= Array.length q);
let len_p = Array.length p in
let len_q = Array.length q in
let n = len_p / 2 in
let a = Array.sub p 0 (len_p - n) in
let b = normalize p n in
if len_q > n then
let c = Array.sub q 0 (len_q - n) in
let d = normalize q n in
let ac = mult_big a c in
let bd = mult_big b d in
let ad_bc = sub_big (sub_big (mult_big (add_big a b) (sum_big c d)) ac) bd
in
add_big (add_big (shift_big ac (2*n)) (shift_big ad_bc n)) bd
else
let aq = mult_big a q in
let bq = mult_big b q in
add_big (shift_big aq n) bq;;
4. Of course the exemple is a bit too much advanced for a tutorial but one can't say mutual recursion is a luxury.
5. As a more general rule, even if during long experience you never have used a language feature, doesn't mean this feature is language-bloating. BrickCaster
-- I wrote that when I was relatively inexperienced in the language. Since then I have written quite a few mutually recursive functions. Richard W.M. Jones
-- I just browsed all my OCaml sources to see if there is a realistic mutual recursion exemple that can well fit in a tutorial, admittedly i can't find one. If i remember correctly, drawing the Dragon curve requires mutual recursion and is a nice beginner exemple. BrickCaster