Eric Radman : a Journal

Mutual Recursion is Useful

Sometimes mutual recursion is characterized as non-trivial, but in my opinion it makes a lot of sennse, and is very useful.

Flattening Nested Loops

In most procedural programming languages fancy nested loops are required when iterating over a stream or structure that must be processed in different modes. Caml doesn't include a break statement, so it's not trivial to hop up and down a latter of nested loops. Caml makes this even harder by using exceptions for such operations as handling EOF.

For these and a few other reasons mutual recursion in a functional language is valuable indeed.

In any document formatting system with macro support including examples of code with special characters is easy because you can set off blocks that are not parsed as native code. For example, in Lout I often document code inside @Listing { ... } defined this way:

macro @Listing{@IndentedDisplay @F @Verbatim}

Unfotuantely XML doesn't give me such a clean method of pluggin in verbatim text.

<listing>
<strong>This is bold text</strong> <!-- I wish! -->
</listing>

So for my for the text posts on this site I logical, but bogus HTML that is displayed with a simple parser that understands my code blocks.

let print_article source =
  let ic = open_in source in
  let rec html_loop ic =
    let ln = (input_line ic) in
      (* code for processing valid HTML *)
      html_loop
  and pre_loop ic =
    let ln = (input_line ic) in
      (* code for processing non-standard preformatted HTML *)
      pre_loop in
  html_loop ic

As you can see let rec pre_loop was replaced with and pre_loop, and now as the print_article function walks line-by-line through the soruce file's input channel it can use it's own logic for switching back and forth between formatting modes.

Example with Logic and EOF handling

After a inserting basic exception handling and pattern matches for the spcial tags the function is very readable because each loop works independantly of the other.

let print_article source =
  let ic = open_in source in
  let rec html_loop ic =
    try
      let ln = (input_line ic) in
      match ln with
          "<code>"  -> print_string "<pre>" ; pre_loop ic
        | _         -> print_string ln ; html_loop ic
    with
       End_of_file -> close_in_noerr ic
  and pre_loop ic =
    try
      let ln = (input_line ic) in
      match ln with
        "</code>" -> print_string "</pre>" ; html_loop ic
      | _         -> print_encoded_ln ln ; pre_loop ic
    with
       End_of_file -> close_in_noerr ic in
  html_loop ic

I suppose high-order functions could accomplish the same task, but if mutual recursion is available, use it!