评估函数时Lisp void-variable错误

时间:2009-09-01 04:45:33

标签: lisp elisp

我正在尝试学习Lisp(实际上是elisp),我尝试将以下函数编写为练习项目Euler Problem 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)))

当我评估它时,我收到以下错误:

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

为什么不识别fn1?如果我试着把(+ fn1 fn2)放在'if'之前它没有抱怨它,那么为什么错误在这里呢?

另外,我意识到这个功能可能实际上并不正确,但是现在我并不担心这个逻辑 - 我稍后会想到这一点。现在,我只对理解这个错误感兴趣。

2 个答案:

答案 0 :(得分:4)

  1. 在功能结束时需要一个额外的括号。
  2. 如果:(+fn1 fn2)应为(+ fn1 fn2),则第二个句子的第一个句子中需要一个空格。 ELisp否则将其读作为将fn2传递给名为+fn1的函数。
  3. 其他一些风格问题:

    1. cond比嵌套if更容易阅读,特别是使用ELisp缩进样式。
    2. =是用于比较数字的常规谓词,而不是equal。虽然equal可行,但读者看起来很有趣。 (至少它在我知道的所有其他Lisp中都有,我可能是错的,因为我也不知道ELisp。)
    3. 以下是我如何重组该功能。

      (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))))
      

      我跑了它,然后它返回一个答案,但我不知道根据项目的euler规范它是否正确。

答案 1 :(得分:2)

不确定这是否解决了你的问题(我没有一个易用的elisp解释器),但是你错过了一个合适的人。在'sum'之后的第一个'if'语句的末尾应该有一个。

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

而不是:

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

我也认为可能还有其他一些问题。