在lambda函数中递归

时间:2011-09-30 07:39:13

标签: recursion lisp common-lisp lambda

我有以下两个功能,我希望合并为一个:

(defun fib (n)
  (if (= n 0) 0 (fib-r n 0 1)))

(defun fib-r (n a b)
  (if (= n 1) b (fib-r (- n 1) b (+ a b))))

我想只有一个功能,所以我试过这样的事情:

(defun fib (n)
  (let ((f0 (lambda (n) (if (= n 0) 0 (funcall f1 n 0 1))))
        (f1 (lambda (a b n) (if (= n 1) b (funcall f1 (- n 1) b (+ a b))))))
    (funcall f0 n)))
然而,这不起作用。确切的错误是*** - IF: variable F1 has no value 就LISP而言,我是初学者,所以我很欣赏以下问题的明确答案:你如何在lisp中编写递归lambda函数?

感谢。

3 个答案:

答案 0 :(得分:18)

LET在概念上同时绑定变量,使用相同的封闭环境来评估表达式。请改用LABELS,它还会在函数名称空间中绑定符号f0f1

(defun fib (n)
  (labels ((f0 (n) (if (= n 0) 0 (f1 n 0 1)))
           (f1 (a b n) (if (= n 1) b (f1 (- n 1) b (+ a b)))))
    (f0 n)))

答案 1 :(得分:4)

您可以使用Graham的alambda替代标签:

(defun fib (n)
  (funcall (alambda (n a b)
             (cond ((= n 0) 0)
                   ((= n 1) b)
                   (t (self (- n 1) b (+ a b))))) 
           n 0 1)) 

或者......你可以稍微看一下这个问题:使用Norvig的defun-memo宏(自动记忆)和一个非尾递归版本的fib来定义一个不具备的fib函数甚至需要辅助函数,更直接地表达fib序列的数学描述,并且(我认为)至少与尾递归版本一样有效,并且在多次调用之后,变得比尾递归版本更有效。 / p>

(defun-memo fib (n)
  (cond ((= n 0) 0)
        ((= n 1) 1)
        (t (+ (fib (- n 1))
              (fib (- n 2))))))

答案 2 :(得分:3)

您也可以尝试这样的事情

(defun fib-r (n &optional (a 0) (b 1) )
  (cond
    ((= n 0) 0)
    ((= n 1) b)
    (T (fib-r (- n 1) b (+ a b)))))

优点:您不必构建包装函数。 Cond constructt负责if-then-elseif场景。您在REPL上将其称为(fib-r 10) => 55

缺点:如果用户向a和b提供值,并且这些值不是0和1,则无法得到正确的答案