我正在尝试在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)))
有谁可以解释为什么我的功能不起作用?
答案 0 :(得分: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
仍然指向汽车为1并且其cdr与以前相同的利弊单元的原始cons单元,与汽车2等等。所有你做的我smake局部变量xs
指向它最初指向的cons单元格的cdr,这是a3
指向的相同的cons单元格。
如果您希望函数更改全局变量a3
的值,请直接执行此操作:
(defun foo () (pop a3))
或者,如果你只想要一个弹出特殊变量列表值的第一个元素的函数,那么你就有了这样一个函数:pop
---只需使用(pop a3)
。
如果你想要一个改变传递它的全局变量值的函数,那么传递变量(即符号)而不是它的值:
(defun foo (var)
(let* ((val (symbol-value var))
(head (car val)))
(set var (cdr val))
head))
(foo 'a3) ; Pop off a3's head and return it.
a3 ; Now a3 has lost its head.
foo
的这个定义就像pop
的一个简单形式,除了它是一个函数,因此评估它的参数。
答案 1 :(得分:0)
这是我的简单解决方案。我在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 ...