The same principal applies in a recursive function call. The
recursive call substitutes a simpler version of the problem, and this
continues until you're only left with the simplest case.
When I first learned about recursion, it seemed like cheating, or
using magic. I would get all tangled up trying to picture arguments
being pushed onto the stack, being popped off, and so on. Eventually,
instead of suddenly seeing how it all worked in a blinding flash, I
just quit worrying about how the language implemented it, and trusted
that the language implementers were much better engineers than I.
Maybe I've reached enlightenment. Anyway, I now let the language
implementers worry about how it works internally, and concentrate on
making sure my recursive calls are dealing with a simpler piece of the
problem at each step.
I hope this helps, but don't feel too bad if it doesn't. If learning
this stuff weren't a little mind-bending, it wouldn't be near as much
fun.
--
Phil Rand
phil...@gmail.com
phil...@pobox.com
> I am rather embarrassed that I cant figure out how the recursion
> example works on page 51.
> It seems far to important for me to glaze over. I would love an
> explicit step by step of what lisp is doing.
The key in understanding recursion is ‘wishful thinking’. Or as Phil
Rand said: 'quit worrying' :-)
When you're *writing* the my-length function, just trust that calling
my-length will do what it's supposed to do: return the length of a
list. Nothing more, nothing less. It's just a function. The fact that
you're still writing that function doesn't matter: once you've
finished writing it it will just work.
The ‘algorithm’ of my-length is quite simple: tally up 1 for the first
element, then add the length of the rest of the list:
(1+ (my-length (cdr lst))) <- trust my-length will work and return
you the length.
Of course, the length of an empty list is 0 (by definition)
So, the entire function simply checks whether the list is empty, in
which case it returns 0.
If the list is not empty, it calls this fantastic function my-length
to calculate the length of the rest of the list and adds 1 to it.
As Phil said, subsitution may also help:
(my-length '()) is 0.
So (my-length '(d)) does 1 + (my-length '()), which is 1 + 0 = 1.
And (my-length '(a b c d)) does 1 + (my-length '(b c d)), which is 1 + 3 = 4.
Just believe my-length does what it's supposed to do and quit worrying.
Hope this helps.
Peter.
> Wow. Thank you all for replying; it is very generous of you all to
> tutor me like this. I do understand now how these 5 lines of
> tremendous code work. I am very happy to get that worked out.
> Purity Control, This explicit explanation is exactly what I needed.
> Thank you for taking the time to type that out.
I'm glad you understand how the runtime handles the recursion. You'll probably have to do the same exercise when LoL discusses tail recursion on p331.
But this was a very simple example; it will be very hard to depict or write down these explicit steps when you get to the more advanced recursive functions in later chapters. You'll get lost very rapidly when you try to understand such a function by expanding it.
Try to understand a recursive function without having to write out the steps, you'll save yourself a lot of trouble.
Here's one for the road :-)
(defun range (min max step)
(if (> min max)
(list)
(cons min (range (+ min step) max step))))
(range 1 10 1) -> (1 2 3 4 5 6 7 8 9 10)
(range 1 10 2) -> (1 3 5 7 9)
(range 999 1 1) -> ()
(don't try this with a negative step value!)
Cheers,
Peter.