Лисп - избавиться от пунктирного списка - PullRequest
0 голосов
/ 05 ноября 2018

Я строю функцию, если Лисп та переворачивает первый и последний элемент списка. Я получаю, что список имеет car и cdr, поэтому в моем выводе есть точка. Есть ли способ убрать точку?

(defun my-butlast (list)
  (loop for l on list
      while (cdr l)
      collect (car l)))

(defun f-l-swap(list)
  (append (last list)(cdr (my-butlast list))(car list))
 )

(write(f-l-swap '(A B C D E)))

OUTPUT:
(E B C D . A)

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Список представляет собой цепочку из cons пар. например. (1 2 3) - это визуализация (1 . (2 . (3 . ()))). В случае, если последний cdr не является (), у вас есть то, что мы называем пунктирным списком, поскольку упрощенная визуализация последней части отсутствует. Он должен быть напечатан с точкой.

У вас есть (E . (B . (C . (D . A)))) и вы хотите иметь (E . (B . (C . (D . (A . ()))))). Вы видите разницу? (car list) это не список, а один элемент, и поэтому вы получаете пунктирный список.

Вот более разумные реализации append и butlast:

(defun my-append (a b)
  (if (null a)
      b
      (cons (car a) (my-append (cdr a) b))))

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

(defun my-append2 (x &rest xs)
  (labels ((helper (x xs)
             (cond ((null xs) x)
                   ((null x) (helper (car xs) (cdr xs)))
                   (t (cons (car x) (helper (cdr x) xs))))))
    (helper x xs)))

Вот butlast

(defun my-butlast (xs)
  (if (null (cdr xs))
      '()
      (cons (car xs) (my-butlast (cdr xs)))))

Теперь действительно нужно сделать это с функциями более высокого порядка или loop, но тогда вы получите скрытые факты о том, как работают списки. Код выше показывает, что они работают.

0 голосов
/ 05 ноября 2018

append ожидает, что аргументы будут списками. В вашем случае (car list) это атом. Вы должны изменить его в список, если вы хотите придерживаться append. То есть:

(defun f-l-swap (list)
  (append (last list)
          (cdr (my-butlast list))
          (list (car list))))
...