CLOS nesnelerini sığ bir şekilde klonlamanın bir yolunu arıyorum, böylece oluşturulan nesne, her bir yuvadaki aynı değerlerle aynı türde olacaktır, ancak yeni bir örnek. Bulduğum en yakın şey, yapılar için bunu yapan standart bir işlev kopyalama yapısıdır.CLOS nesnelerini klonlamak için genel bir yöntem var mı?
cevap
Genel olarak CLOS nesnelerini kopyalamak için standart önceden tanımlanmış bir yol yoktur. Mümkünse, mümkün olan en doğru olanı, keyfi nesneler için doğru olanı yapan makul bir varsayılan kopyalama işlemi sağlamak, eğer mümkün ise, sınıftan sınıfa ve uygulamadan uygulamaya doğru doğru semantikler değiştiği için önemsiz değildir. MOP'un sağladığı genişletilmiş olanaklar, böyle bir varsayılanı sağlamak için daha da zorlaştırır. Ayrıca, CL'de, bir çöp toplama dili olmak, nesnelerin kopyalanmasına gerçekten çok ihtiyaç duyulmamaktadır, örn. Parametre olarak veya iade edildiğinde. Dolayısıyla, kopyalama işlemlerinizi gerektiği gibi uygulamak muhtemelen en temiz çözüm olacaktır.
(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))
Sen class-slots
ve slot-definition-name
bazı MOP desteğine ihtiyaç duyacaktır: Burada söyleniyor
Ne istediğini yapmak olabilir benim pasajı dosyalarından birinde bulunabilir budur.
(muhtemelen an old c.l.l thread bu benimsemiş, ama ben gerçekten böyle bir şey ihtiyacım olmadı, bu yüzden tamamen denenmemiş olduğunu hatırlamıyorum..)Sen (CCL ile test) bu gibi kullanabilirsiniz:
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>
İşte danlei tarafından sunulan işlevin biraz farklı bir versiyonu. Bunu bir süre önce yazdım ve bu yazıya rastladım. Tamamen hatırlamadığım nedenlerden dolayı, kopyalamadan sonra REINITIALIZE-INSTANCE. Ben düşünün
gibi ek initargs'ları ileterek yeni nesnede bazı değişiklikler yapabilirsiniz.
(copy-instance *my-account* :balance 100.23)
Bu, ayrıca 'standart nesne' olan nesneler üzerinde genel işlev olarak tanımlanır. Yapılması gereken doğru şey olabilir veya olmayabilir.
(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))))
Tam olarak aradığım şey; Common Lisp'de bu varsayılan olarak mevcut olmadığına şaşırdım. – MicroVirus
Yuva bağlı veya bağlı değilse, bir sınama eklemek yararlı olabilir. Ardından, yuvaya bağlıysa, yalnızca yuva değerine erişin. –
Haklısınız - Testi ekledim. Teşekkürler! – danlei
İlan edildiği şekilde çalışır. Burada daha çok veya daha az taşınabilir şekilde çalışması gerektiğini bir ithalat beyanı var: '(: \t # + dan-ithalat-gölgeleme openmcl-yerli-ipler #: CCL \t # + cmu #: pcl \t # + SBCL #: sb-pCL \t # + lispworks #: hCl \t # + allegro #: paspas \t # + clisp #: Pl \t #: sınıf yuva #: yuva çözünürlüklü-ad) '. – Inaimathi