tags:

views:

155

answers:

2

I'm trying to learn Lisp (elisp, actually), and I tried writing the following function as an exercise (Project Euler #2):

(defun sumfib (n fn1 fn2 sum)
  "Calculate Fibonacci numbers up to 4,000,000 and sum all the even ones"
  (if (< 4000000 (+ fn1 fn2))
      sum
    (if (equal n 3)
        (sumfib 1 (+ fn1 fn2) fn1 (+ sum (+fn1 fn2)))
      (sumfib (+ n 1) (+ fn1 fn2) fn1 sum)))

When I evaluate it I get the following error:

Debugger entered--Lisp error: (void-variable fn1)
  (+ fn1 fn2)
  (< 4000000 (+ fn1 fn2))
...

Why wouldn't it recognize fn1? If I try to put (+ fn1 fn2) before the 'if' it doesn't complain about it there, so why the error here?

Also, I realize the function may not actually be correct, but for now I'm not worried about the logic - I'll figure that out later. For now, I'm only interested in understanding this error.

+1  A: 

Not sure if this solves your problem (I don't have an elisp interpreter handy), but you're missing a right paren. There should be one at the end of the first 'if' statement, after 'sum'.

  (if (< 4000000 (+ fn1 fn2))
      sum)

instead of:

 (if (< 4000000 (+ fn1 fn2))
      sum

I also think there might be some other issues in there.

Sam DeFabbia-Kane
Ooh, I am missing a parenthesis... It's not after the first 'if' though, as that's supposed to be and 'if-else'. Thanks.
Tal Pressman
Ah, ok. I'm used to Scheme, which does things a bit differently. Glad I was at least somewhat helpful.
Sam DeFabbia-Kane
+3  A: 
  1. You need an extra close parenthesis at the end of your function.
  2. You need a space in the first clause of the second if: (+fn1 fn2) should be (+ fn1 fn2). ELisp otherwise reads it as passing fn2 to a function named +fn1.

Couple of other style issues:

  1. A cond is a lot easier to read than nested ifs, especially using ELisp indentation style.
  2. = is the normal predicate used for comparing numbers, not equal. Although equal will work, it looks funny to the reader. (At least it does in all the other Lisps I know, I could be wrong because I don't know ELisp as well.)

Here's how I'd restructure the function.

(defun sumfib (n fn1 fn2 sum)
  "Calculate Fibonacci numbers up to 4,000,000 and sum all the even ones"
  (cond 
    ((< 4000000 (+ fn1 fn2)) sum)
    ((= n 3) (sumfib 1 (+ fn1 fn2) fn1 (+ sum (+ fn1 fn2))))
    (t (sumfib (1+ n) (+ fn1 fn2) fn1 sum))))

I ran it, and it returns an answer, but I don't know if it's right according to the project euler specification.

Nathan Sanders