递归时优先粘合列表——单点返回

发布于 2024-11-02 09:42:03 字数 1689 浏览 1 评论 0原文

警告:绝对 Lisp n00b。我非常精通 Java,对 C 也有一定程度的了解。Lisp……到目前为止还不是我最喜欢的。 (但它比序言更好......)

我想迭代一个列表并优先返回该列表的子集。

我已经成功编写了代码,该代码将使用 (append ) 函数在堆栈展开时拆分列表并重建它。然而,当我尝试加入条件时,我遇到了很大的麻烦。

(defun split-then-rebuild-list (row value llist)
   (cond ((not (eq llist nil))
          (let ((item (first llist))
                (rval nil))
            (print llist)
            (print "Entering next recursion level")
            (setf rval (split-then-rebuild-list row value (cdr llist)))
            (print "Left recursion")
            (print "Current item: ")
            (princ item)
            (print "Received: ")
            (Princ rval)
            (print "Appended:")
            (setf x (first(first item)))
            (and (eq row x) (eq value (nth 2 (first item)))
                 (print "gluing: ")
                 (princ rval)
                 (princ item)
                 (setf rval (append rval item )))))))

当 NIL 展开时,它会不断地从堆栈中返回。我不明白的是为什么当我输入 (set tmp (list ABC) ) 然后 (append tmp nil) 它返回 (ABC) 但不在我这里的代码中。对我来说,我会以这样的方式阅读这篇文章:“在所有情况下都返回 nil,但在这些条件下返回一个列表。如果两个列表项满足条件,它们将被附加,否则它应该只返回上一个递归级别的列表.

[编辑]提供更多信息。
我原来的函数可以很好地分解和重建:

(defun splitThenRebuildList( llist )
        (cond(
        (not (eq llist nil ))
        (let(
        (item (first llist))
        (rval)
        );end let decl
        (print llist )
        (setf rval (splitThenRebuildList( cdr llist )))
        (print "item: ")(princ item)
        (print "Received: ") (Princ rval)
        (append rval item )
        );end let
        ));end cond
)

由于第一个发布的代码是一个流产,有什么建议可以修改它以获得我需要的东西吗?

Warning: Absolute Lisp n00b. I'm very well versed in Java, and moderately in C. Lisp... so far hasn't been my favorite. (But its better than prolog...)

I want to iterate through a list and preferentially return a subset of that list.

I've successfully wrote code that will tear apart the list and rebuild it as the stack unwinds using the (append ) function. However, when I try to throw in conditions I get significant trouble.

(defun split-then-rebuild-list (row value llist)
   (cond ((not (eq llist nil))
          (let ((item (first llist))
                (rval nil))
            (print llist)
            (print "Entering next recursion level")
            (setf rval (split-then-rebuild-list row value (cdr llist)))
            (print "Left recursion")
            (print "Current item: ")
            (princ item)
            (print "Received: ")
            (Princ rval)
            (print "Appended:")
            (setf x (first(first item)))
            (and (eq row x) (eq value (nth 2 (first item)))
                 (print "gluing: ")
                 (princ rval)
                 (princ item)
                 (setf rval (append rval item )))))))

NIL just keeps getting returned right up the stack as it unwinds. What I don't understand is why when I type (set tmp (list A B C) ) then (append tmp nil) it returns (A B C) but not in the code as I have it here. To me, I would read this in a way that would say " return nil in all cases but a list under these conditions. If two list items met the condition, they would be appended otherwise it should just return the list from the previous recursion level.

[EDITED] to provide additional information.
My original function that works just fine for breaking apart and rebuilding:

(defun splitThenRebuildList( llist )
        (cond(
        (not (eq llist nil ))
        (let(
        (item (first llist))
        (rval)
        );end let decl
        (print llist )
        (setf rval (splitThenRebuildList( cdr llist )))
        (print "item: ")(princ item)
        (print "Received: ") (Princ rval)
        (append rval item )
        );end let
        ));end cond
)

Any suggestions to modify this to get what I need since the first posted code is an abortion?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情绪少女 2024-11-09 09:42:03

在对您的问题的评论中,我建议remove-if-not。这是一个使用它的示例,我猜您自己的函数也尝试这样做。这是你有意还是无意的?

(defun filter-by-row-and-value (row value seq)
  (remove-if-not (lambda (x)
                   (and (eql row (first x))
                        (eql value (third x))))
                 seq
                 :key #'first))

正如其他人已经指出的,您自己的代码不符合您的预期的原因可能是您将调试输出语句放入 and 表单中。对于该特定情况,我建议使用

(when (and conditions...)
  debugging-output
  return-value)

而不是

(and conditions...
     debugging-output
     return-value)

In the comments to your question, I've suggested remove-if-not. Here's an example using it that does what I guess your own function tries to do, too. Is this what you intend or not?

(defun filter-by-row-and-value (row value seq)
  (remove-if-not (lambda (x)
                   (and (eql row (first x))
                        (eql value (third x))))
                 seq
                 :key #'first))

As others have already noted, the reason your own code doesn't what you expect is probably that you've put debugging output statements inside the and form. For that specific case, I'ld suggest using

(when (and conditions...)
  debugging-output
  return-value)

instead of

(and conditions...
     debugging-output
     return-value)
旧时光的容颜 2024-11-09 09:42:03

真的很难说出你想做什么。以下是您可能尝试执行的操作的示例。

这是一个函数,它接受一个值和一个列表,并返回列表的子集,其元素是 cons 对,其 car 是 eq3。如果您愿意,您可以使测试变得更复杂。

(defun do-something-to-list (value list)
  (cond ((null list)
     nil)
    ((eq value (first (first list)))
     (cons (first list)
       (do-something-to-list value (rest list))))
    (t
     (do-something-to-list value (rest list)))))

实际应用:

(do-something-to-list 3 '((3 9) (a b c) (47 3) (3 zztop) (blah)))
((3 9) (3 zztop))

注意:使用 common-lisp 中的内置例程有多种方法可以完成此类操作,但看起来您只是想学习如何理解递归。

It's really hard to tell what you're trying to do. Here's an example of what you might be trying to do.

This is a function which takes a value and a list, and returns the subset of the list whose elements are a cons pair whose car is eq to 3. You can make the test more complicated if you want.

(defun do-something-to-list (value list)
  (cond ((null list)
     nil)
    ((eq value (first (first list)))
     (cons (first list)
       (do-something-to-list value (rest list))))
    (t
     (do-something-to-list value (rest list)))))

In action:

(do-something-to-list 3 '((3 9) (a b c) (47 3) (3 zztop) (blah)))
((3 9) (3 zztop))

Note: there are various ways to do this kind of thing using built-in routines in common-lisp, but it looks like you're just trying to learn how to understand recursion.

梦里兽 2024-11-09 09:42:03

如果从代码中删除 (princ rval)(princ item),该函数就可以工作。

(split-then-rebuild-list :a 4 '(((:a nil 4))((:b nil 5))))

=>
((:A NIL 4))

要在递归展开时重建列表,请在匹配项的测试为 false 时返回一个值。

If you remove (princ rval) and (princ item) from the code, the function works, sort of.

(split-then-rebuild-list :a 4 '(((:a nil 4))((:b nil 5))))

=>
((:A NIL 4))

To rebuild the list as the recursion unwinds, return a value when the test for a matching item is false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文