复制符号函数

The copy-symbol function

Common Lisp 提供了许多用于复制对象的函数;即 copy-listcopy-alistcopy-seqcopy-structurecopy-treecopy-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
  1. 我可以一次性给voldemort所有谜语(除了他的symbol-name),还是有必要复制过来symbol-value, symbol-plist, symbol-packagesymbol-function分别来自谜语? (HyperSpec 给出了使用示例,但它们不处理 intern 将复制的符号命名为新名称。)

  2. copy-symbol 通常用于什么(它还可以用于什么)?

(setf (get symbol key) new-value) 在符号对象上设置 属性。因此,每个使用符号 riddle 的地方都是相同的符号,因此它将具有相同的 属性 列表。 属性 列表用于语言的实现方面,它不是创建对象的方法。早期的 lisp 用它来存储全局函数、全局值、全局宏。 Moderns 对它的口齿不清,但它保留下来是为了向后兼容。

(setq riddle "gifted magician")

这会更新一个已经存在的变量 riddle 以与字符串 "gifted magician"

相关联
(setf (get 'riddle :school) "Hogwarts")

这与变量riddle(字符串"gifted magician")无关,但是你在全局符号riddle上做了一个属性。 CL 使用 属性 列表来存储调试信息,早期的 lisp 将其用作全局范围。这不是创建对象的方法。

(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 
(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:

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"