Is this implementation truely tail-recursive?

Posted by CFP on Stack Overflow See other posts from Stack Overflow or by CFP
Published on 2010-06-03T21:21:19Z Indexed on 2010/06/03 21:34 UTC
Read the original article Hit count: 236

Hello everyone!

I've come up with the following code to compute in a tail-recursive way the result of an expression such as 3 4 * 1 + cos 8 * (aka 8*cos(1+(3*4)))

The code is in OCaml. I'm using a list refto emulate a stack.

type token = 
    Num of float
  | Fun of (float->float)
  | Op of (float->float->float);;

let pop l = let top = (List.hd !l) in l := List.tl (!l); top;;
let push x l = l := (x::!l);;
let empty l = (l = []);;
let pile = ref [];;

let eval data =
  let stack = ref data in

  let rec _eval cont =
    match (pop stack) with
      | Num(n) -> cont n;
      | Fun(f) -> _eval (fun x -> cont (f x));
      | Op(op) -> _eval (fun x -> cont (op x (_eval (fun y->y))));
  in _eval (fun x->x)
;;

eval [Fun(fun x -> x**2.); Op(fun x y -> x+.y); Num(1.); Num(3.)];;

I've used continuations to ensure tail-recursion, but since my stack implements some sort of a tree, and therefore provides quite a bad interface to what should be handled as a disjoint union type, the call to my function to evaluate the left branch with an identity continuation somehow irks a little.

Yet it's working perfectly, but I have the feeling than in calling the _eval (fun y->y) bit, there must be something wrong happening, since it doesn't seem that this call can replace the previous one in the stack structure... Am I misunderstanding something here?

I mean, I understand that with only the first call to _eval there wouldn't be any problem optimizing the calls, but here it seems to me that evaluation the _eval (fun y->y) will require to be stacked up, and therefore will fill the stack, possibly leading to an overflow...

Thanks!

© Stack Overflow or respective owner

Related posts about optimization

Related posts about ocaml