LISP: обращение к списку в LISP с использованием RPLACA/RPLACD/NCONC

Поэтому я пытаюсь сделать так, чтобы функция брала список и переворачивала его, но я не уверена, как бы использовать RPLACA/RPLACD/NONC, По сути, делает то же самое, что и наоборот, но использует узлы минусов исходного списка и не выделяет никаких узлов минусов. То, что я до сих пор

(defun rip(lst)
(cond   (( null lst) 0)
    ((eq (nil) (cdr (last lst))) 1)
    (((setq x (car (last lst)))
     (rplaca (car (last lst)) (car first lst))
     (rplaca (car first lst) x)) + 2 rip(butlast(rest lst)))))

2 ответа

Поэтому я считаю, что это был ответ, который они искали:

Recursive: 
(define rip (lst)
(if (null lst) nil (nconc (rip (rest lst))(rplacd lst nil))))

Non-Recursive:
(defun rip (lst)
(do ((res nil) (todo (rest lst)(rest lst)))
    ((null lst) res)
  (setf res (rplacd lst res))
  (setf lst todo) ))

Таким образом, потенциальный аргумент списка будет (1 2), Мы могли бы представить, что аргумент находится в списке с адресом #A и выглядит так:

#A=(1 . #B)
#B=(2 . nil) 

Для каждого минуса мы создаем локальную переменную хранения cdr перед установкой cdr к предыдущему cons который ноль для первого cons, Когда текущий cons является nil Вы сделали, и результат предыдущий cons, Результат для нашего примера:

#A=(1 . nil)
#B=(2 . #A) 

Единственная мутирующая функция, которая вам понадобится rplacd так как единственное, что меняется, это cdr, Функция может выглядеть примерно так:

(defun nreverse (list)
  (labels ((aux (list prev)
             (if (endp list)
                 <??>
                 (let ((next <??>))
                   (rplacd <??> <??>)
                   (aux <??> <??>)))))
    (aux list nil)))

Или, если вы не против утечки, вы можете сделать это:

(defun nreverse (list &optional prev)
  (if (endp list)
      <??>
      (let ((next <??>))
        (rplacd <??> <??>)
        (nreverse <??> <??>))))
Другие вопросы по тегам