Elisp 中 lambda 的递归

Mir*_*lov 3 emacs recursion lambda elisp

我有以下Python代码:

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)
Run Code Online (Sandbox Code Playgroud)

我想把它翻译成 Emacs Lisp。在Elisp 的高阶函数中,我被告知不要使用defuninside 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)))
Run Code Online (Sandbox Code Playgroud)

然而,该函数i在分配之前被调用let,并且我收到错误 -*** Eval error *** Symbol's value as variable is void: i

我如何在 Elisp 中的 lambda 中进行递归?

Tao*_*eng 6

是的,你可以在 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)
Run Code Online (Sandbox Code Playgroud)

主要思想是使用辅助 lambda ( lambda1) 调用真实 lambda ( lambda2) 并将真实 lambda ( lambda2) 传递给自身。