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