I'm trying to solve Project Euler question 2 with Lisp. This recursive solution blows the stack on execution, but I thought Lisp (using clisp) would recognize the tail recursion. This is being entered into the top-level.
(defun e2-problem (&optional (f1 1) (f2 1) (sum 0))
"Sum fibonacci sequence, even terms up to 4 million"
(if (> f2 4000000) sum)
(e2-problem f2 (+ f1 f2) (if (evenp f2)
(+ sum f2)
sum))
Is my implementation not correctly arranged for optimization? I imagine this would hinder my Lisp education quite a bit if I could not rely on idiomatic recursion.
Your code implements an endless loop. It does not terminate.
Using LOOP:
Recursion (or even iteration) is not necessary!
Every third Fibonacci number is even:
and since each even Fibonacci number (in bold) is the sum of the two preceding odd Fibonacci numbers, the sum of the even Fibonacci numbers up to Fn is exactly half of the sum of all the Fibonacci numbers up to Fn (if Fn is even, of course).
Now, the sum of the first n Fibonacci numbers is Fn+2 − 1. This is easy to check by induction: the sum of the first n + 1 Fibonacci numbers is F1 + F2 + ... + Fn + Fn+1, which equals Fn+2 − 1 + Fn+1 by hypothesis, which equals Fn+3 − 1 by the definition of the Fibonacci numbers.
So if you can find the largest N such that F3N ≤ 4,000,000, then the sum that’s asked for will be (F3N+2 − 1) / 2.
(I'll leave the remaining details to you but it should be straightforward from here.)
For an environment to implement tail call elimination is mandatory in Scheme, but not in most other Lisp dialects, such as Common Lisp.
1) Correct syntax error in code:
2) use SBCL. CLISP is not kind enough to detect tail recursion.
3) use highest available optimization level: