为何Common Lisp中push元素后原列表未出现新增元素?
问题解析:Common Lisp中
push对子列表操作未影响原列表的原因 先看你的代码运行后的实际输出:
(5 2 3) (1 2 3)
核心原因:列表的结构与push的本质
在Common Lisp里,列表是由cons单元串联起来的:
'(1 2 3)实际是(cons 1 (cons 2 (cons 3 nil))),三个cons单元依次指向。tl2 = (cdr l2)让tl2指向的是l2的第二个cons单元(也就是(cons 2 (cons 3 nil)))。
而push 5 tl2的本质等价于:
(setq tl2 (cons 5 tl2))
它并没有修改原来的那个(cons 2 (cons 3 nil))单元,而是创建了一个新的cons单元(cons 5 (cons 2 (cons 3 nil))),然后把tl2这个变量的指向改成了这个新单元。
原列表l2的第一个cons单元,它的cdr仍然指向原来的(cons 2 (cons 3 nil)),所以l2的输出还是(1 2 3)。
如何让原列表跟着变化?
如果你想修改原列表的结构,需要直接修改l2的cdr部分,比如用setf操作:
(defvar l2) (defvar tl2) (setq l2 '(1 2 3)) (setf (cdr l2) (cons 5 (cdr l2))) ; 直接修改l2的cdr (print l2) ; 此时输出(1 5 2 3)
这样操作是直接修改了l2第一个cons单元的cdr指向,让它指向新创建的(cons 5 (cons 2 (cons 3 nil))),原列表的结构就会改变。
内容的提问来源于stack exchange,提问作者CS Leaner
相关产品推荐
相关产品推荐

