我正在尋找一種以淺的方式克隆CLOS對象的方法,因此創建的對象將具有相同類型,並且每個插槽中的值相同,但是是一個新實例。我發現最接近的是一個標準的功能複製結構,它可以爲結構做到這一點。克隆CLOS對象是否有一種通用方法?
6
A
回答
10
通常沒有標準的預定義方式來複制CLOS對象。如果可能的話,提供合理的默認複製操作(至少)大部分時間爲任意對象執行正確的操作並不是微不足道的,因爲正確的語義從類到類以及從應用程序到應用程序都會發生變化。 MOP提供的擴展可能性使得提供這種默認更加困難。而且,在CL中,作爲垃圾收集語言,對象的拷貝並不是經常需要的,例如,當作爲參數傳遞或返回時。因此,根據需要實施複製操作可能是最乾淨的解決方案。
話雖這麼說,這裏是我在我的代碼片段文件一經發現,這可能會做你想要什麼:
(defun shallow-copy-object (original)
(let* ((class (class-of original))
(copy (allocate-instance class)))
(dolist (slot (mapcar #'slot-definition-name (class-slots class)))
(when (slot-boundp original slot)
(setf (slot-value copy slot)
(slot-value original slot))))
copy))
您將需要class-slots
和slot-definition-name
一些MOP支持。
(我大概是從an old c.l.l thread採用了這一點,但我不記得我從來沒有真的需要這樣的事情,所以這是完全未經測試。)
你可以使用它像這樣(CCL測試):
CL-USER> (defclass foo()
((x :accessor x :initarg :x)
(y :accessor y :initarg :y)))
#<STANDARD-CLASS FOO>
CL-USER> (defmethod print-object ((obj foo) stream)
(print-unreadable-object (obj stream :identity t :type t)
(format stream ":x ~a :y ~a" (x obj) (y obj))))
#<STANDARD-METHOD PRINT-OBJECT (FOO T)>
CL-USER> (defparameter *f* (make-instance 'foo :x 1 :y 2))
*F*
CL-USER> *f*
#<FOO :x 1 :y 2 #xC7E5156>
CL-USER> (shallow-copy-object *f*)
#<FOO :x 1 :y 2 #xC850306>
4
下面是danlei提交的函數的一個稍微不同的版本。我前一段時間寫了這個,只是偶然發現了這篇文章。由於我不完全記得的原因,複製後這稱爲REINITIALIZE-INSTANCE。我認爲它是這樣的,你可以通過傳遞額外的initargs到這個函數來對新對象進行一些改變
例如,
(copy-instance *my-account* :balance 100.23)
這也被定義爲'標準對象'的對象上的泛型函數。這可能或可能不是正確的做法。
(defgeneric copy-instance (object &rest initargs &key &allow-other-keys)
(:documentation "Makes and returns a shallow copy of OBJECT.
An uninitialized object of the same class as OBJECT is allocated by
calling ALLOCATE-INSTANCE. For all slots returned by
CLASS-SLOTS, the returned object has the
same slot values and slot-unbound status as OBJECT.
REINITIALIZE-INSTANCE is called to update the copy with INITARGS.")
(:method ((object standard-object) &rest initargs &key &allow-other-keys)
(let* ((class (class-of object))
(copy (allocate-instance class)))
(dolist (slot-name (mapcar #'sb-mop:slot-definition-name (sb-mop:class-slots class)))
(when (slot-boundp object slot-name)
(setf (slot-value copy slot-name)
(slot-value object slot-name))))
(apply #'reinitialize-instance copy initargs))))
+1
正是我在找的東西;我很驚訝這在Common Lisp中默認不存在。 – MicroVirus
相關問題
- 1. 是否有可能使用Object.assign克隆一個對象的方法?
- 2. 通用對象克隆解決方案
- 3. 是否有一種更簡單的方法來克隆具有數十個成員變量的對象?
- 4. 如何檢查一個對象是否可以通過結構化克隆算法進行克隆
- 5. 克隆對象
- 6. PHP:檢查對象是否是克隆(任何對象)?
- 7. 對象是否通過引用破壞工作或克隆對象
- 8. 克隆一個對象
- 9. 克隆對象只有一些參數
- 10. 如何用一個get方法克隆標籤對象?
- 11. 克隆方法
- 12. 是否有可能獲得克隆的jQuery對象的高度?
- 13. 克隆Java對象
- 14. PHP - 對象克隆
- 15. 克隆dom.Document對象
- 16. 深克隆對象
- 17. 通用java覆蓋克隆方法
- 18. 幾次克隆對象的最快方法是什麼
- 19. 這是克隆ES6中對象的好方法嗎?
- 20. 使用包來克隆一個對象?
- 21. 鎖性能克隆對象與否
- 22. 保存CLOS對象
- 23. 有效克隆未知的對象不支持克隆
- 24. 是否有一種測試Python中兩個對象的屬性是否等價的通用方法?
- 25. Threejs克隆方法
- 26. 克隆方法使用構造函數創建對象
- 27. 如何使用clone()方法克隆Java對象
- 28. 在Singleton對象上調用克隆方法時出現錯誤
- 29. 什麼是複製/克隆JSON對象結構的最有效方法?
- 30. 什麼是克隆對象的instanceof?
如果插槽綁定或不綁定,添加測試可能會很有用。然後只有在插槽被綁定時訪問插槽值。 –
你說得對 - 我添加了測試。謝謝! – danlei
按廣告製作。這裏有一個import語句應該使其在更多或更少的可移植的方式工作:'(:陰影 - 導入 - 從 \t#+ openmcl本地線程#:CCL \t#+ CMU#:PCL \t# + SBCL#:SB-PCL \t#+ lispworks#:鹽酸 \t#+快板#:拖把 \t#+ CLISP#:CLOS \t#:類時隙#:槽定義名稱)'。 – Inaimathi