Вопрос:
Я пытаюсь написать функцию в Common Lisp, которая удаляет элемент из списка. Вот что я написал до сих пор:
(defun aux-remove-fio (lst toremove) (if (equal (first lst) toremove) (pop lst) (aux-remove-fio (rest lst) toremove))))
Когда я тестирую функцию, вот результат:
CG-USER(49): a3 ((1 (1 . 1) (1 . 2)) (2 (2 . 1) (1 . 2))) CG-USER(50): (pop a3) (1 (1 . 1) (1 . 2)) CG-USER(51): a3 ((2 (2 . 1) (1 . 2))) CG-USER(52): (setf a3 ‘((1 (1 . 1) (1 . 2)) (2 (2 . 1) (1 . 2)))) ((1 (1 . 1) (1 . 2)) (2 (2 . 1) (1 . 2))) CG-USER(53): (aux-remove-fio a3 ‘(1 (1 . 1) (1 . 2))) (1 (1 . 1) (1 . 2)) CG-USER(54): a3 ((1 (1 . 1) (1 . 2)) (2 (2 . 1) (1 . 2)))
Может ли кто-нибудь объяснить, почему моя функция не работает?
Лучший ответ:
Да. Ваша функция меняет значение своей локальной переменной, lst — больше ничего.
Вот более простой пример, показывающий то же самое:
(setq a3 ‘(1 2 3)) ; (1 2 3) (defun foo (xs) (setq xs (cdr xs))) ; Change value of xs. ;; Change value of xs to (2 3). Its initial value is the value of a3, i.e., (1 2 3) (foo a3) a3 ; => (1 2 3)
После того, как foo называется, a3 все еще указывает на оригинальную ячейку cons, чей автомобиль равен 1 и чей cdr является той же самой ячейкой cons, что и раньше, с автомобилем 2 и т.д. Все, что вы сделали, я smake локальная переменная xs указывает на cdr минусов ячейку, на которой она первоначально указывала, которая была той же самой ячейкой cons, на которую указывает a3.
Если вы хотите, чтобы ваша функция изменила значение глобальной переменной a3, сделайте это прямо:
(defun foo () (pop a3))
Или, если вам просто нужна функция, которая выталкивает первый элемент из значения списка специальной переменной, тогда у вас есть такая функция: pop — just use (pop a3).
Если вам нужна функция, которая изменяет значение глобальной переменной, которую вы передаете, передайте переменную (то есть, символ), а не ее значение:
(defun foo (var) (let* ((val (symbol-value var)) (head (car val))) (set var (cdr val)) head)) (foo ‘a3) ; Pop off a3 head and return it. a3 ; Now a3 has lost its head.
Это определение foo похоже на простую форму pop, за исключением того, что это функция, поэтому оценивает ее аргумент.
Ответ №1
Это мое простое решение. Я определяю функцию в REPL
CL-USER> (defun remove-element (mylist n) (append (subseq mylist 0 n) (subseq mylist (1+ n))))
затем запустите его (ошибки в реализации Lisp могут отличаться)
CL-USER> (remove-element ‘(1 2 3 4 5) 0) (2 3 4 5) CL-USER> (remove-element ‘(1 2 3 4 5) 1) (1 3 4 5) CL-USER> (remove-element ‘(1 2 3 4 5) 5) ; Evaluation aborted on #<SB-KERNEL:BOUNDING-INDICES-BAD-ERROR … CL-USER> (remove-element ‘(1 2 3 4 5) -1) ; Evaluation aborted on #<TYPE-ERROR …