Example: Recursion Without Rec

Here's a neat trick that's possible with refs: we can build recursive functions without ever using the keyword rec. Suppose we want to define a recursive function such as fact:

let rec fact n = 
  if n = 0 then 1 else n * fact (n-1)

Abstracting a little, that function has the following form:

let rec f x = 
  ... some code including a recursive call [f y] from some argument [y] ...

We can instead write the following:

let f0 = 
  ref (fun x -> x)

let f x = 
  ... replace [f y] with [!f0 y] ...

let () = f0 := f

Now f will compute the same result as it did in the version where we defined it with rec. What's happening here is sometimes called "tying the recursive knot": we update the reference to f0 to point to f, such that when f dereferences f0, it gets itself back! The initial function to which we made f0 point (in this case the identity function) doesn't really matter; it's just there as a placeholder until we tie the knot.

Here's an example of that with the factorial function:

let fact0 =
  ref (fun x -> x)

let fact n =  (* note: no [rec] *)
  if n = 0 then 1 else n * (!fact0) (n-1)

let () = fact0 := fact

let x = fact 5 (* ==> 120 *)

results matching ""

    No results matching ""