我是Lisp的新手。通过函数删除列表中的项目会反映在函数外部,但插入不会。我怎样才能插入相同的内容?
例如
(defun test (a b)
(delete 1 a)
(delete 5 b)
(append '(5) b)
(member '5 b))
(setq x '(2 3 1 4))
(setq y '(8 7 5 3))
(test x y)
;;x and y after function ends
x
(2 3 4)
y
(8 7 3)
为什么不附加影响列表y?如何从函数中插入y?
答案 0 :(得分:2)
为什么不附加影响列表y?
append 文档的第一句是(强调添加):
追加返回一个新列表,它是副本的串联。
没有人说过追加应该修改一个列表。
如何从函数中插入y?
在最普遍的意义上,你不能。如果 y 的值是空列表,会发生什么?使用函数(而不是宏)无法在Common Lisp中创建类似的工作:
(let ((list '())
(insert list 1)
l)
;=> (1)
函数不能改变其范围 1 之外的变量的词法绑定,因此 insert 无法更改 list 。
当然,您可以修改对象的内部结构,因此如果 list 的值是某些非空列表,则可以修改该列表的结构。 list 的值不会改变(即,它仍然是相同的cons单元格),但该cons单元格所代表的列表将会改变。例如,
(defun prepend (list element)
(let ((x (first list)))
(setf (rest list) (list* x (rest list))
(first list) element)))
(let ((list (list 1 2)))
(prepend list 'a)
list)
;=> (a 1 2)
一般来说,你需要养成保存功能结果的习惯。大多数函数不会修改它们的参数,因此您需要保存它们的结果。某些功能允许,但不是必需,以修改其参数,并且不必以可预测的方式进行修改,因此您还需要保存其结果。例如,您的代码可能是:
(defun test (a b)
(setf a (delete 1 a))
(setf b (delete 5 b))
(setf b (append '(5) b))
(member 5 b))
(test ...)
;=> true
1 你可以通过给它一个关闭绑定等的setter函数来解决这个问题。但是那些技术将是变通方法。