Я проходил это учебное пособие для развлечения и застрял на самом последнем, что он говорит: «Упражнение. Дайте линейно рекурсивную реализацию объединения и различия». (для списка)
Союз, без пота.
Разница, пот.
Попытка выглядит следующим образом. , .
(defun list-diff (L1 L2)
(cond
((null L1) L2)
((null (member (first L1) L2)) (cons (first L1) (list-diff (rest L1) L2)))
(t (list-diff (rest L1) L2))
)
)
Теперь, это возвращает все элементы, которые находятся в L1, которых нет в L2, но это просто возвращает все L2 (очевидно). Точно так же, если я изменю L2 в строке 3 на «ноль», то он просто возвращает все L1, которых нет в L2, но ни один из L2.
Мои попытки обходных путей не выглядят рекурсивными, и когда они появляются, я получаю переполнение стека (например, если я пытаюсь вызвать (list-diff L2 L1) где-нибудь).
Любые другие его упражнения, такие как пересечение списков, требуют только прохождения элементов L1. Здесь я хочу выделить важные элементы из L2 или выполнить (list-diff L2 L1), а затем объединить результаты обоих, но это больше не является линейно-рекурсивным.
Мысли?
(на самом деле не домашняя работа. Я просто подумал, что попробую посмотреть на какой-нибудь LISP для удовольствия.)
РЕДАКТИРОВАТЬ: функция, которая делает это правильно, на основе ответов:
(defun list-diff (L1 L2)
(cond
((null L1) nil)
((null (member (first L1) L2)) (cons (first L1) (list-diff (rest L1) L2)))
(t (list-diff (rest L1) L2))
)
)