Mar*_*ñoz 5 lisp sbcl common-lisp literals clos
为什么在sbcl中发生这种情况?也许是个bug?
(defclass myclass ()
((s1
:initform '((a . 1) (b . 2)))
(s2
:initform '((a . 1) (b . 2)))))
(defparameter ins (make-instance 'myclass))
(setf (cdr (assoc 'a (slot-value ins 's1))) 43) ;; change only slot s1
;; here my problem
(slot-value ins 's1) ;; => ((a . 44) (b . 2)))
(slot-value ins 's2) ;; => ((a . 44) (b . 2)))
Run Code Online (Sandbox Code Playgroud)
但如果改变:initform to:
(defclass myclass ()
((s1
:initform '((a . 1) (b . 2)))
(s2
:initform '((a . 1) (b . 3)))))
Run Code Online (Sandbox Code Playgroud)
问题消失了
我在sbcl 1.4.3和1.4.11中测试了这个.在clisp中似乎没有出现问题.
Sva*_*nte 13
不.您正在修改文字数据,这会产生不确定的后果.
当您在源代码中引用列表时,这意味着您要使用的内容正是读者从源代码生成的列表 - 这是一个文字列表.读者可能会记住这些事情,因此两个相同的列表不会重复.
解决此问题的一种方法是在运行时创建列表,使用list和cons:
(defclass myclass ()
((s1
:initform (list (cons a 1) (cons b 2)))
(s2
:initform (list (cons a 1) (cons b 2)))))
Run Code Online (Sandbox Code Playgroud)
这不是一个错误.'((a . 1) (b . 2))是一个文字常量,因为所有常量都是不可变的.这意味着所有出现的'(a . 1)也是文字只能指向car另一个,因为它永远不会改变
现在实现可以选择创建新结构,以便CLISP可以这样做,但你不能依赖于此.你不应该改变文字数据.
如果要更改它,则需要使用深层副本,如下所示:
(defclass myclass ()
((s1
:initform (copy-tree '((a . 1) (b . 2))))
(s2
:initform (copy-tree '((a . 1) (b . 2))))))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
89 次 |
| 最近记录: |