【问题标题】:Common Lisp: Why does this function cause infinite recursion?Common Lisp:为什么这个函数会导致无限递归?
【发布时间】:2011-10-29 13:16:06
【问题描述】:

我正在尝试编写一个类似于 list 的函数 (lnn; list-not-nil),它只附加非 nil 的值。

(list nil 3) --> (NIL 3)
(lnn nil 3) --> (3)

这是我到目前为止的代码。由于某种原因,它会在我尝试的任何输入上导致无限递归。

(defun lnn (&rest items)
  (lnn-helper nil items))

(defun lnn-helper (so-far items)
   (cond ((null items)
           so-far)
     ((null (car items))
      (lnn-helper so-far (cdr items)))
     (t (lnn-helper (append so-far (list (car items))) (cdr items)))))

有什么想法吗?非常感谢。

【问题讨论】:

    标签: lisp common-lisp infinite-loop


    【解决方案1】:
    (defun lnn-helper (so-far &rest items)
      ...)
    

    使用此参数列表,如果您始终使用两个参数调用 lnn-helper,items 将永远不会是 nil。删除&rest 说明符,它会起作用。

    【讨论】:

    • 谢谢,我做了这个更正,但我仍然得到无限递归。
    • @Miriam 它对我有用:(lnn nil 3) => (3); (lnn 1 2 nil 3) => (1 2 3)。什么输入会导致无限递归?
    • 我也很想将元素放在 SO-FAR 的头部,然后通过返回 (NREVERSE SO-FAR) 结束,这对于短列表无关紧要,但 APPEND 是 O( n) 所以 LNN-HELPER 最终是 O(n^2)。
    【解决方案2】:

    Matthias 的回答应该有所帮助。另请注意,这只是一个简单的简化:

    (defun lnn (&rest elements)
      (reduce (lambda (elt acc) (if elt (cons elt acc) acc))
              elements
              :from-end t
              :initial-value nil))
    

    甚至(效率较低):

    (defun lnn (&rest elements)
      (reduce #'cons (remove nil elements) :from-end t :initial-value nil))
    

    然后:

    (defun lnn (&rest elements)
      (remove nil elements))
    

    :)

    P.S.:我知道这可能只是一个递归练习,但是 SCNR。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-10
      • 2021-08-30
      • 1970-01-01
      • 2011-11-11
      • 2019-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多