2012-11-13 42 views
2

我有以下Python代碼:遞歸拉姆達在elisp的

def sum_fibonacci(): 
    '''Project Euler: 2 
    Sum of even-valued terms of Fibonacci sequence < 4 mil 
    ''' 
    def i(a, b, acc): 
     if a >= 4000000: return acc 
     if a % 2 == 0: 
      return i(a + b, a, acc + a) 
     else: return i(a + b, a, acc) 
    return i(2, 1, 0) 

我想將它翻譯成的Emacs Lisp。在Higher-order functions in Elisp我被告知不要在defun內使用defun,因爲它啓用了全局函數,所以我寫了lambda代替。但是我需要遞歸地調用lambda。

我的代碼是:

(defun sum-fibonacci() 
    (let ((i 
     (lambda (a b acc) 
      (cond ((>= a 4000000) acc) 
       ((evenp a) (funcall i (+ a b) a (+ a acc))) 
       (t (funcall i (+ a b) a acc)))))) 
    (funcall i 2 1 0))) 

但是它與let分配前的功能i被調用,我得到一個錯誤 - *** Eval error *** Symbol's value as variable is void: i

怎樣在elisp的做遞歸拉姆達?

+0

您可能還想發現'flet'。 – tripleee

回答

4

Recursing in a lambda functionlabels重寫了它:

(defun sum-fibonacci() 
    (labels ((i (a b acc) 
       (cond ((>= a 4000000) acc) 
        ((evenp a) (i (+ a b) a (+ a acc))) 
        (t (i (+ a b) a acc))))) 
    (i 2 1 0))) 
2

只需刪除逗號在lambda列表:

(defun sum-fibonacci() 
    (labels ((rec (a b acc) 
       (cond ((>= a 4000000) acc) 
         ((evenp a) (rec (+ a b) a (+ a acc))) 
         (t (rec (+ a b) a acc))))) 
    (rec 2 1 0))) 
4

是的,你可以的Emacs Lisp做到這一點。

(funcall (lambda (fib a b acc) (funcall fib a b acc fib)) ;;lambda1 
     (lambda (a b acc fib)       ;;lambda2 
      (cond ((>= a 40000) acc) 
       ((zerop (mod a 2)) (funcall fib (+ a b) a (+ acc a) fib)) 
       (t (funcall fib (+ a b) a acc fib)))) 
     2 1 0) 

主要思想是使用輔助拉姆達(lambda1)來調用實際拉姆達(lambda2),並通過實際拉姆達(lambda2)本身。