2012-06-16 24 views
6

मैं क्लोज़ ऑब्जेक्ट्स को उथले ढंग से क्लोन करने का एक तरीका ढूंढ रहा हूं, इसलिए बनाई गई वस्तु प्रत्येक स्लॉट में समान मानों के साथ एक ही प्रकार का होगा, लेकिन एक नया उदाहरण। मुझे मिली सबसे नज़दीकी चीज एक मानक फ़ंक्शन कॉपी-स्ट्रक्चर है जो संरचनाओं के लिए यह करती है।क्या CLOS ऑब्जेक्ट्स क्लोन करने के लिए कोई सामान्य तरीका है?

उत्तर

10

सामान्य रूप से CLOS ऑब्जेक्ट्स की प्रतिलिपि बनाने के लिए कोई मानक पूर्वनिर्धारित तरीका नहीं है। यदि संभव हो तो यह मामूली नहीं है, एक उचित डिफ़ॉल्ट प्रतिलिपि ऑपरेशन प्रदान करने के लिए जो मनमाने ढंग से वस्तुओं के लिए सही समय (कम से कम) सही समय पर करता है, क्योंकि सही अर्थशास्त्र कक्षा से कक्षा में और आवेदन से आवेदन में बदल जाता है। एमओपी प्रदान की गई विस्तारित संभावनाएं इस तरह के एक डिफ़ॉल्ट प्रदान करने के लिए और भी कठिन बनाती हैं। इसके अलावा, सीएल में, एक कचरा एकत्रित भाषा होने के नाते, वस्तुओं की प्रतिलिपि वास्तव में अक्सर की आवश्यकता नहीं होती है, उदा। जब पैरामीटर के रूप में पारित किया गया या लौटाया गया। इसलिए, आवश्यकतानुसार अपनी प्रतिलिपि संचालन को लागू करना शायद सबसे साफ समाधान होगा।

(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 के लिए कुछ एमओपी समर्थन की आवश्यकता होगी:

, यहाँ कहा जा रहा है कि क्या मैं अपने टुकड़ा फ़ाइलों में से एक में पाया है, जो तुम क्या चाहते हो सकती है।

(मैं शायद an old c.l.l thread से इसे अपना लिया है, लेकिन मैं याद नहीं कर सकते मैं वास्तव में कुछ इस तरह की जरूरत कभी नहीं, तो यह पूरी तरह से अपरीक्षित है।।)

आप (सीसीएल के साथ परीक्षण) इस तरह इसका इस्तेमाल कर सकते हैं:

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> 
+5

यदि स्लॉट बाध्य है या नहीं तो परीक्षण जोड़ने के लिए उपयोगी हो सकता है। फिर स्लॉट मान केवल तभी प्राप्त करें, यदि स्लॉट बाध्य है। –

+1

आप सही हैं - मैंने परीक्षण जोड़ा। धन्यवाद! – danlei

+1

विज्ञापित के रूप में काम करता है। यहाँ एक आयात बयान यह एक अधिक या कम पोर्टेबल तरीके से काम करना चाहिये कि बताया गया है: '(: छाया-आयात से \t # + openmcl देशी-धागे #: सीसीएल \t # + CMU #: PCL \t # + SBCL #: sb-PCL \t # + LispWorks #: एचसीएल \t # + Allegro #: झाड़ू \t # + clisp #: क्लोस \t #: वर्ग स्लॉट #: स्लॉट परिभाषा-नाम) '। – Inaimathi

4

यहाँ समारोह danlei द्वारा प्रस्तुत की एक अलग संस्करण है। मैंने इसे थोड़ी देर पहले लिखा था और इस पोस्ट में बस ठोकर खाई। उन कारणों के लिए जिन्हें मैं पूरी तरह याद नहीं करता हूं, यह प्रतिलिपि बनाने के बाद पुनरीक्षण-इंस्टेंस का आह्वान करता है। I सोचें ऐसा इसलिए है कि आप इस फ़ंक्शन

उदा। इस अतिरिक्त अतिरिक्त 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

बिल्कुल वही जो मैं खोज रहा था; मुझे आश्चर्य हुआ कि यह सामान्य लिस्प में डिफ़ॉल्ट रूप से मौजूद नहीं है। – MicroVirus