Subject: Re: Was not making tail recursion elmination a mistake?
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 12 Jun 2004 21:38:54 -0500
Newsgroups: comp.lang.lisp
Message-ID: <5cqdncK1x4GjI1bd4p2dnA@speakeasy.net>
Gareth McCaughan  <gareth.mccaughan@pobox.com> wrote:
+---------------
| Marco Baringer <mb@bese.it> writes:
| > ...
|
| I think what you want is, with the definition of RUN-TRAMPOLINED above,
|     (defun func1 () #'func2)
|     (defun func2 () #'func1)
| or, if you need to be able to pass arguments around,
|     (defun run-trampolined (func args)
|       (catch 'done
|         (loop ... )))
+---------------

Actually, you don't even need the THROW to pass arguments around:
just use closures over the args:

    > (defun work (who)
	(princ who)
	(princ " ")
	(force-output)
	(sleep 1))

    WORK
    > (defun func1 ()
	(work 1)
	(let ((n (random 100)))
	  (if (> n 50)
	    (lambda () (func3 1 n))
	    #'func2)))

    FUNC1
    > (defun func2 ()
	(work 2)
	(let ((n (random 100)))
	  (if (> n 50)
	    (lambda () (func3 2 n))
	    #'func1)))

    FUNC2
    > (defun func3 (who what)
	(format t "3: func~a said '~a'~%" who what)
	(cond
	  ((> what 95) nil)
	  ((= who 1) #'func2)
	  (t #'func1)))

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

    RUN-TRAMPOLINED
    > (run-trampolined (lambda () (func3 0 0)))	; fake "func0"
    3: func0 said '0'
    2 1 2 3: func2 said '86'
    1 2 3: func2 said '61'
    1 2 3: func2 said '83'
    1 3: func1 said '74'
    2 1 3: func1 said '76'
    2 3: func2 said '62'
    1 3: func1 said '54'
    2 3: func2 said '51'
    1 2 1 2 1 2 3: func2 said '88'
    1 3: func1 said '97'
    NIL
    > 


-Rob

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