复制符号函数
The copy-symbol function
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
我可以一次性给voldemort所有谜语(除了他的symbol-name
),还是有必要复制过来symbol-value
, symbol-plist
, symbol-package
和symbol-function
分别来自谜语? (HyperSpec 给出了使用示例,但它们不处理 intern
将复制的符号命名为新名称。)
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"
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
我可以一次性给voldemort所有谜语(除了他的
symbol-name
),还是有必要复制过来symbol-value
,symbol-plist
,symbol-package
和symbol-function
分别来自谜语? (HyperSpec 给出了使用示例,但它们不处理intern
将复制的符号命名为新名称。)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"