From: Juanma Barranquero

Subject: On tail-recursion, closures and other newbie questions

Date: 1998-8-26 7:26

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm reading the interesting book _On Lisp_, by Paul Graham, where the
author postulates that sometimes it is better and/or more natural to
develop an algorithm like a tail-recursive function (instead of
iterative) and notes that that should incur no penalty because most
implementations are very good at optimizing tail-recursion. Then he
shows some examples in which a non-tail-recursive function can be
translated into one (that hopefully will be optimized by the
compiler).

So I tried to test it with ACL 5.0.beta for Windows and found a
puzzling (to me, anyway) result.

Compiling:

(defun fact-rec (n r)
  (declare (optimize (speed 3) (safety 0) (size 3) (debug 0))
           (integer r)
           (fixnum n))
  (cond ((<= n 1) r)
        (t (fact-rec (1- n) (* n r)))))

gives a very short (and tail-optimized) 42 bytes subroutine.

Then I tried to give to that a more user-friendly (fact N) wrapper,
like so:

(defun fact (num)
  (declare (optimize (speed 3) (safety 0) (size 3) (debug 0))
           (fixnum num))
  (labels ((fact-rec (n r)
             (declare (fixnum n)
                      (integer r))
             (cond ((<= n 1) r)
                   (t (fact-rec (1- n) (* n r))))))
    (fact-rec num 1)))

where obviously the labels-defined fact-rec is identical to the
subroutine above. And now I get a 80-byte subroutine *plus* another
one (the closure) of 65 bytes. The difference is appaling. Why?

                                                       /L/e/k/t/u


-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 5.5.3i; see <http://www.pgpi.com>

iQA/AwUBNePh9v4C0a0jUw5YEQIXVACfWuXrdVY4vqnKnCJV21L8uWOTPiQAn1Ie
4OCUmDqt2KxWX2E2+FNYzVSm
=9zsb
-----END PGP SIGNATURE-----