如何将此递归解决方案转换为迭代解决方案?

时间:2014-11-02 04:38:48

标签: algorithm lisp elisp

我在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

1 个答案:

答案 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))