Subject: Re: Was not making tail recursion elmination a mistake?
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 12 Jun 2004 21:00:53 -0500
Newsgroups: comp.lang.lisp
Message-ID: <9_udnX0g163IKFbd4p2dnA@speakeasy.net>
Simon Katz <simon3@nomistech.com> wrote:
+---------------
| The THROWs cause the loop to exit. Try this:
| 
| (defun func1 ()
|   (princ "1 ")
|   (sleep 1)
|   (lambda ()
|     (func2)))
+---------------

Even simpler:

  (defun func1 ()
    (princ "1 ")
    (sleep 1)
    #'func2)

You only need to use LAMBDA here if you want to pass some closed-over
arguments to the next function in the chain.

+---------------
| (defun func2 ()
|   (princ "2 ")
|   (sleep 1)
|   #'func1)
| 
| (defun run-trampolined (func)
|   (loop for f = func then (funcall f)))
| 
| (run-trampolined #'func1)
+---------------

Yup! This is the standard "CPS by returning to trampoline" hack
used in so many C-based implementations of Scheme!  ;-}

Although one typically wants to permit the state machine to exit
without having to throw an exception, e.g., returning NIL stops it:

  (defun run-trampolined (func)
    (loop for f = func then (funcall f)
	  while f))


-Rob

p.s. Note: On any system which buffers *STANDARD-OUTPUT* by default,
you'll need a FORCE-OUTPUT after each PRINC to see anything...  ;-}  ;-}

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607