开发者

Preferentially gluing lists on recursion--Single point of return

开发者 https://www.devze.com 2023-02-26 07:04 出处:网络
Warning:Ab开发者_StackOverflow中文版solute 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...)

Warning: Ab开发者_StackOverflow中文版solute 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?


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)


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消