[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tail recursion, again



    Date: Sun, 9 Sep 1990 12:30 EDT
    From: Reti@Riverside.scrc.symbolics.com

	Date: Tue, 4 Sep 90 11:21:09 CDT
	From: lsmith@CLI.COM (Larry Smith)

	Last spring I got very frustrated with the Symbolics because the
	compiler could not optimize tail recursion. Does Genera 8 do any
	better?  

	Thanks,

	Larry Smith
	Computational Logic, Inc.  
    [Disclaimer:  this is my personal understanding, not any official statement
    from Symbolics.]

    Genera uses stack frames to hold important information about the dynamic
    state of the function running in the frame (e.g. if it has changed the
    trap mode, if it has a presentation to a stack-consed object, if a trap
    on exit has been requested via the debugger, if there is an open catch
    or unwind-protect, etc.).  If you did the traditional tail-recursion
    optimization you would only have one actual stack frame in which to
    store this state for potentially a large number of recursive calls to
    the same function.  This makes it much harder to do the 'traditional'
    tail recursion optimization because you have to arrange to store this
    state elsewhere, which would slow down all function call/returns. 

There are two kinds of "tail recursion" optimizations.  Something like

(defun foo (n)
  (catch 'foo
    (if (= n 0)
	(bar)
	(foo (1- n)))))

isn't tail recursive since there is state when FOO calls itself.
However, it can still be turned into something like:

(defun foo (n)
  (catch 'foo
    (tagbody
       loop
         (cond ((= n 0) 
	        (bar))
               (t (setq n (1- n))
		  (go loop))))))

because the catches can all be collapsed into a single catch.  This is
the case you were talking about, and would would be hard for us to do.

Quite a bit easier (on Ivory, anyways) is the case where there is a call
to any function for destination return with no cleanups needing to be
done.  Trap on exit would work well enough.