Преимущественное склеивание списков при рекурсии - единая точка возврата - PullRequest
0 голосов
/ 17 апреля 2011

Предупреждение: Absolute 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 A B C) ), тогда (append tmp nil) возвращает (A B C), но не в коде, как у меня здесь. Для меня, я бы прочитал это так, что бы сказать «вернуть ноль во всех случаях, но список при этих условиях. Если два элемента списка удовлетворяют условию, они будут добавлены, в противном случае он должен просто вернуть список с предыдущего уровня рекурсии .

[ИЗДАНО] для предоставления дополнительной информации.
Моя оригинальная функция, которая прекрасно работает для разделения и восстановления:

(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
)

Какие-либо предложения изменить это, чтобы получить то, что мне нужно, так как первый опубликованный код является аборт?

Ответы [ 3 ]

2 голосов
/ 17 апреля 2011

В комментариях к вашему вопросу я предложил 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)
0 голосов
/ 17 апреля 2011

Если вы удалите (princ rval) и (princ item) из кода, функция сработает, вроде.

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

=> ((: A NIL 4))

Чтобы перестроить список, когда рекурсия раскручивается, верните значение, когда тест на соответствующий элемент имеет значение false.

0 голосов
/ 17 апреля 2011

Трудно сказать, что ты пытаешься сделать.Вот пример того, что вы могли бы пытаться сделать.

Это функция, которая принимает значение и список и возвращает подмножество списка, элементами которого являются пара минусов, чьиавтомобиль от eq до 3.Вы можете сделать тест более сложным, если хотите.

(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))

Примечание: существуют различные способы сделать это, используя встроенные подпрограммы вобычный, но похоже, что вы просто пытаетесь научиться понимать рекурсию.

...