我正在尝试将列表传递给Lisp中的函数,并在函数内更改该列表的内容,而不会影响原始列表.我已经读过Lisp是按值传递的,这是真的,但还有其他事情我不太明白.例如,此代码按预期工作:
(defun test ()
(setf original '(a b c))
(modify original)
(print original))
(defun modify (n)
(setf n '(x y z))
n)Run Code Online (Sandbox Code Playgroud)
如果你调用(测试),即使(修改)返回(xyz),它也会打印(abc).
但是,如果您尝试仅更改列表的一部分,则无法正常工作.我认为这与列表中的内容在内存中相同或者类似的内容有关?这是一个例子:
(defun test ()
(setf original '(a b c))
(modify original)
(print original))
(defun modify (n)
(setf (first n) 'x)
n)Run Code Online (Sandbox Code Playgroud)
然后(测试)打印(xbc).那么如何更改函数中list参数的某些元素,就好像该列表是该函数的本地列表一样?
lisp function common-lisp parameter-passing pass-by-reference
来自 Common Lisp HyperSpec 词汇表:
树ñ。1. 由 conses 和 atom 组成的二进制递归数据结构:conses 本身也是树(有时称为“子树”或“分支”),而原子是终端节点(有时称为叶子)。通常,叶子代表数据,而分支在这些数据之间建立某种关系。2. 一般来说,任何具有“分支”和叶子概念的递归数据结构。
树形结构ñ。(一棵树的)构成这棵树的一组 conses。请注意,虽然每个这样的 cons 的 car[1b] 组件是树结构的一部分,但作为树中每个 cons 的汽车的对象本身并不是其树结构的一部分,除非它们也是 conses。
树结构定义中的最后一句提出了一个问题,那就是,cdrs 也可以这样说吗?
在“树”的定义中使用二进制一词似乎表明就树而言,汽车与 cdr 之间没有区别,但是“树结构”的定义似乎对汽车特殊对待,所以我很困惑。
我创建了一个函数来从嵌套列表中随机选择一个"位",例如,((1 0 0 1) (1 1 1 1) (0 1 0 1))然后翻转它.如果是一个,则将其设为零,反之亦然.该函数运行良好,但我发现尽管我复制了它,它仍会改变原始参数.这是函数,最后两个写入演示了这个问题.如果我((1 1 1 1))转到这个,我希望看到这个原始值打印,(write DNA-seq)但原来是修改,所以(write DNA-seq)并(write CDNA-seq)打印相同的东西.
(defun rand-mutate (DNA-seq)
(let ((CDNA-seq (copy-list DNA-seq)))
(let ((gene (random-range 0 (length CDNA-seq))))
(let ((base (random-range 0 (length (nth gene CDNA-seq)))))
(cond ((= (nth base (nth gene CDNA-seq)) 0) (setf (nth base (nth gene CDNA-seq)) 1))
(t (setf (nth base (nth gene CDNA-seq)) 0))) (write DNA-seq)(write CDNA-seq)))))
Run Code Online (Sandbox Code Playgroud)