Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lisp 如何在不修改原始列表内容的情况下修改列表内容_Lisp - Fatal编程技术网

Lisp 如何在不修改原始列表内容的情况下修改列表内容

Lisp 如何在不修改原始列表内容的情况下修改列表内容,lisp,Lisp,正在尝试创建列表的副本。我使用了复制列表,但这会修改原始列表,因此我无法使用复制列表,并且复制树不工作。如有任何建议,将不胜感激 (defun switch-var (var list_a) (let ((temp (copy-list list_a))) (setf (cdr (assoc var temp)) (not (cdr (assoc var temp))))temp)) 例如,在lisp中,我将创建一个列表,然后调用switch var (setf *list_a* '((A

正在尝试创建列表的副本。我使用了复制列表,但这会修改原始列表,因此我无法使用复制列表,并且复制树不工作。如有任何建议,将不胜感激

(defun switch-var (var list_a)
 (let ((temp (copy-list list_a)))
 (setf (cdr (assoc var temp)) (not (cdr (assoc var temp))))temp))
例如,在lisp中,我将创建一个列表,然后调用switch var

(setf *list_a* '((A NIL) (B T) (C T) (D NIL)))

* (switch-var ’b *list_a*)

;I will get this which is ok
((A NIL) (B NIL) (C T) (D NIL))

;but if i call it again

* (switch-var ’b *list_a*)

;I will get this which is not ok
((A NIL) (B T) (C T) (D NIL))

;so techincally I do not want to modify the original list_a 
;in the function I just want to modify the temp 

您的示例代码存在不止一个问题

第一个已经在评论中指出<代码>复制列表复制给定的列表,但不复制该列表的元素。这意味着您应该使用
copytree

第二个原因是setf并没有修改您似乎认为正在修改的位置

使用您的示例代码,当我第一次计算
(开关变量'b*list_a*)
时,结果是list
((a NIL)(b)(C T)(D NIL))
,我们可以注意到它不同于list
((a NIL)(b NIL)(C T)(D NIL))

当我第二次计算
(开关变量'b*list_a*)
时,结果是list
((a NIL)(b.T)(C T)(D NIL))
,我们可以注意到它不同于list
((a NIL)(b T)(C T)(D NIL))

考虑一下列表
(bt)
与配对
(bt)
缺点方面的区别。第一个可以通过计算
(cons'b(cons t nil))
来构建。第二个可以通过计算
(cons'bt)
来构建。这将直接引导您解决问题,并解决问题

关于您在使用
copy tree
时仍然存在问题的评论,您可以通过执行以下操作来确认
copy tree
是否按预期工作:

CL-USER> (defvar *test-alist* '((a nil) (b t) (c t) (d nil)))
*TEST-ALIST*
CL-USER> (defun lists-share-p (list1 list2)
           (intersection list1 list2 :test #'eq))

LISTS-SHARE-P
CL-USER> (lists-share-p *test-alist* (copy-list *test-alist*))
((D NIL) (C T) (B T) (A NIL))
CL-USER> (lists-share-p *test-alist* (copy-tree *test-alist*))
NIL

当我遇到一些问题,这些问题看起来可能在语言提供的函数/表单中工作不太正常时,执行类似于上述的小型简单测试来确认或纠正我对这些函数/表单的理解是非常有用的,因为它们通常会导致对函数/表单的正确理解,或者使我正确地理解代码中的错误。您自己可能也会发现这种情况。

最好使用循环在一次过程中复制和修改列表。或者地图,但我更喜欢环

(defparameter *foo* '((a . nil)
                      (b . t)
                      (c . t)
                      (d . nil)))

(defun switch-variable (var list)
  (loop
     for (name . val) in list
     collecting (cons name
                      (if (eql name var)
                          (not val)
                          val))))

(switch-variable 'b *foo*)
;=> ((A) (B) (C . T) (D))
(switch-variable 'b *foo*)
;=> ((A) (B) (C . T) (D))

对变量使用cons单元格而不是列表更有效。打印时,它不会显示
NIL
,但这只是视觉效果(值仍然是
NIL
)。

就成对而言,基本上如下所示(我尝试近似“cons-box”,但在相同的空间中,我将内部列表与列表一样):

一旦运行了
复制列表
,您就有了以下内容(顶部是原始的,底部是
复制列表
的返回值):

然后浏览并修改复制的顶级列表:

[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
  v            v            v            v
  (A NIL)      (B NIL)      (C T)        (D NIL)
  ^            ^            ^            ^
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
在这一点上,您已经修改了一个内部列表,您没有复制它。如果您使用了
复制树
,则会出现以下情况(顶部是原始的,底部是从
复制树
返回的):


此时,内部列表也会被复制,您可以随意对其进行破坏性修改,而无需修改原始列表。

请修复代码格式,并解释
复制列表
复制树
的具体错误(包括完整错误消息&c)。您没有修改列表。您确实修改了列表的内容元素。好吧,但是如何在不影响原始内容的情况下修改列表的内容元素呢?我纠正了以前的错误,并进行了递归调用,现在我第二次调用cdr时,它不再是B。但是现在它是bt,但是使用树并不能修复不修改原始文件的问题。也许我不明白你的意思,但谢谢你的帮助。@BlackKnight我认为在这里递归并不重要,除非你想自己修改结果,而不是使用
复制树
。从
复制树
返回的结果不应该与原始列表有任何共享结构,并且当我在给定代码中使用
复制树
而不是
复制列表
时,我看不到对原始列表的任何修改。我想可能有一个古老的定义,比如在你的问题中,你定义了
开关变量
,然后继续调用
开关变量
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
  v            v            v            v
  (A NIL)      (B T)        (C T)        (D NIL)
  ^            ^            ^            ^
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
  v            v            v            v
  (A NIL)      (B NIL)      (C T)        (D NIL)
  ^            ^            ^            ^
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL
  v            v            v            v
  (A NIL)      (B T)        (C T)        (D NIL)

  (A NIL)      (B T)        (C T)        (D NIL)
  ^            ^            ^            ^
[ | . --]--> [ | . --]--> [ | . --]--> [ | . --]--> NIL