How to explain this ...
The problem is that 'unless' does not end the function - the calls
to 'loop' are *not* in tail position, so although you are recursing,
you are not tail-recursing. Your code doesn't exit at the bottom
but rather unwinds the call stack, returning from 'loop' and and
evaluating 'result' every time. At the top level, 'result' is the
empty list (passed as the argument) and that is what is being
returned.
Contrast with:
(if (>= num-stored n)
result
(if (>= (* u (- N num-seen)) (- n num-stored))
(loop (add1 num-seen) num-stored result)
(loop (add1 num-seen) (add1 num-stored) (cons num-seen
result))))
When you have this kind of multiple test logic, 'cond' is your
friend:
(cond
((>= num-stored n)
result)
((>= (* u (- N num-seen)) (- n num-stored))
(loop (add1 num-seen) num-stored result))
(else
(loop (add1 num-seen) (add1 num-stored) (cons num-seen
result))))
Hope this helps,
George