我在Lisp中有以下递归函数
(defun f (item tree)
(when tree
(if (equal item (car tree)) tree
(if (and (listp (car tree))
(equal item (caar tree)))
(car tree)
(if (cdr tree)
(f item (cdr tree)))))))
此函数接收树和项以在其直接离开中查找。如果 item 是任何子列表的汽车,那么它将返回该子列表。也就是说,
(f 'c '(a b c)) => (c)
(f 'b '(a b c)) => (b c)
(f 'a '((a 1 2) b c)) => (a 1 2)
我最近被告知(Emacs Lisp)没有进行尾递归优化,因此我建议将其转换为while
循环。我在Lisp的所有训练都避免像这样的循环。 (我坚持认为他们 un -functional,但那是边缘迂腐。)我已经做了以下尝试以获得更加符合标准的风格:
(defun f (item tree)
(let ((p tree))
(while p
(cond
((equal item (car p)) p)
((and (listp (car p))
(equal item (caar p)))
(car tree))
(t (f item (cdr p))))
(setq p (cdr p)))))
为了简洁/清晰,我缩短了功能名称,但如果您是emacs的超级用户,请查看where it is being used。
答案 0 :(得分:3)
你的"迭代"解决方案仍在递归中。它也没有返回cond
表达式中的值。
以下版本将变量设置为找到的结果。如果找到了结果,则循环结束,因此可以返回。
(defun f (item tree)
(let ((p tree)
(result nil))
(while (and p (null result))
(cond ((equal item (car p)) (setq result p))
((and (listp (car p))
(equal item (caar p)))
(setq result (car tree)))
(t (setq p (cdr p)))))
result))