Common Lisp提供了许多复制对象的功能;即copy-list
,copy-alist
,copy-seq
,copy-structure
,copy-tree
和copy-symbol
。但是,copy-symbol
似乎与其他人的运作方式略有不同。所有其他人(最值得注意的是copy-structure
)都成功地采用了一般模式:
(setq riddle "gifted magician") ;set some value for Tom Riddle
"gifted magician"
(setf (get 'riddle :school) "Hogwarts") ;install a property for him
"Hogwarts"
(setq voldemort (copy-symbol 'riddle t)) ;attempt to clone him
#:RIDDLE
(get 'voldemort :school) ;failed magic
NIL
我可以一次给伏地魔一切谜语(除了symbol-name
除外),还是需要复制symbol-value
,symbol-plist
,symbol-package
,和谜语中的symbol-function
分开? (HyperSpec提供了使用示例,但它们并未以新名称处理intern
复制的符号。)
copy-symbol
通常用于什么(以及它可能用于什么)?
答案 0 :(得分:2)
(setf (get symbol key) new-value)
在符号对象上设置属性。因此,使用符号riddle
的每个位置都是相同的符号,因此它将具有相同的属性列表。属性列表用于语言的实现方面,它不是制作对象的方法。早期的lisps用它来存储全球功能,全球价值,全球宏观。现代人对我们的关注很少,但它仍然是为了向后兼容。
(setq riddle "gifted magician")
这会更新已存在的变量riddle
以与字符串“gifted magician”相关联
(setf (get 'riddle :school) "Hogwarts")
这与变量riddle
(字符串“天才魔术师”)无关,但您在全局符号riddle
上创建了一个属性。 CL使用属性列表来存储调试信息,而早期的lisps使用它作为全局范围。这不是创建对象的方法。
(setq voldemort (copy-symbol 'riddle t))
这使得带有属性列表的符号riddle
的副本和符号值与voldemort
相关联,因此:
voldemort ; ==> riddle (looks the same, but is a copy)
(eq voldemort 'riddle) ; ==> nil
(get voldemort :school) ; ==> "Hogwarts"
以下是使用classes and objects:
执行此操作的方法(defclass magician ()
((name :initarg :name)
(description :initarg :description :initform "")
(school :initarg :school :initform nil)))
(defparameter *riddle*
(make-instance 'magician :name "Tom Riddle"
:description "gifted magician")
(setf (slot-value *riddle* 'school) "Hogwarts")
; see http://stackoverflow.com/questions/11067899/is-there-a-generic-method-for-cloning-clos-objects
(defparameter *voldemort* (shallow-copy-object *riddle*))
(slot-value *voldemort* 'school) ; ==> "Hogwarts"
(setf (slot-value *riddle* 'school) "Other")
(slot-value *voldemort* 'school) ; ==> "Hogwarts"
(slot-value *riddle* 'school) ; ==> "Other"
如何使用structures:
结构在场景之后做得更多,比如make访问器和构造函数,但它们不如CLOS类灵活,并且它们只有单继承。在示例中,它几乎可以正常工作。
(defstruct magician name (description "") (school nil))
(defparameter *riddle* (make-magician :name "Tom Riddle"
:description "Gifted magician"))
(setf (magician-school *riddle*) "Hogwarts")
(defparameter *voldemort* (copy-structure *riddle*))
(magician-school *voldemort*) ; ==> "Hogwarts"
(setf (magician-school *riddle*) "Other")
(magician-school *voldemort*) ; ==> "Hogwarts"
(magician-school *riddle*) ; ==> "Other"