2010-12-16 16 views
10

Scalar::Util::weaken का कहना है:पर्ल में, एक कमजोर संदर्भ की प्रतिलिपि क्यों एक सामान्य, मजबूत, संदर्भ बनाते हैं?

नोट: एक कमजोर संदर्भ प्रतिलिपि बनाई जा रही एक सामान्य, मजबूत, संदर्भ बनाता है।

मुझे समझ में नहीं आ रहा है कि पर्ल इसे इस तरह क्यों संभालता है। मेरे अनुप्रयोगों में, मैं चक्रों को तोड़ने के लिए weaken का उपयोग करता हूं। कभी-कभी मुझे उन संदर्भों को कमजोर करना पड़ता है जो पहले से कमजोर होंगे यदि पर्ल इस तरह से कार्य नहीं करेगा।

उत्तर

10

मुझे लगता है कि यह एक encapsulation मुद्दा है। यदि कोई तृतीय पक्ष लाइब्रेरी आंतरिक रूप से कमजोर रेफरी का उपयोग करती है तो मेरे कोड को समय से पहले यह जानने की उम्मीद नहीं की जानी चाहिए कि जब मैं किसी संदर्भ की प्रति बना देता हूं तो यह अचानक मुझ पर गायब हो सकता है। पर्ल में सामान्य उम्मीद यह है कि एक रेफरी तब तक वैध रहेगी जब तक यह अस्तित्व में न हो। जब आप weaken पर कॉल करते हैं तो आपने मूल रूप से वादा किया है कि आप यह जांचने के लिए आवश्यक कदम उठाएंगे कि इसका उपयोग करने से पहले संदर्भ अभी भी मान्य है।

एक दूसरे कारण के रूप में एक कमजोर रेफरी की एक मजबूत प्रति को कमजोर करने के लिए इंटरफ़ेस काफी स्ट्रेट आगे है।

my $new_ref = $old_ref; if (isweak($old_ref)) { weaken($new_ref); } 

एक कमजोर रेफरी कमजोर रेफरी बनाने के लिए एक मजबूत रेफरी पाने के लिए ऐसा करने के लिए कोड थोड़ा अधिक जटिल है।

my $new_ref; 
if (ref($old_ref) eq 'ARRAY') { 
    $new_ref = \@{$old_ref}; 
} 
elsif (ref($old_ref) eq 'HASH') { 
    $new_ref = \%{$old_ref}; 
} 
elsif (..... 

क्या आप जानते हैं रेफरी केवल एक ही प्रकार हो सकता है आप if/elsif झरना बचा सकता है और केवल deref-reref करते हैं, लेकिन यह अभी भी न्याय के लिए कारण है कि आप एक नया संदर्भ लेने के लिए सिर्फ dereferenced कठिन है तो। अगला रखरखाव आपके कोड को 'ठीक करने' का प्रयास करेगा।

3

मुझे यकीन है कि क्यों इस डिफ़ॉल्ट व्यवहार है नहीं कर रहा हूँ, लेकिन यहाँ Scalar::Util प्रलेखन से समाधान कोड के आधार पर है:

$ref = \$foo; 
$weak = isweak($ref);    # false 
weaken($ref); 
$weak = isweak($ref);    # true 

# copying a weak reference creates a new strong one 
$copy = $ref; 
$weak = isweak($copy);    # false 

# the solution is simply to weaken the copy 
$weaken($copy); 
$weak = isweak($copy);    # true 

यदि आप एक सबरूटीन कि एक तर्क के रूप में कमजोर संदर्भ ले लिया बनाना चाहते थे और उस संदर्भ की एक कमजोर प्रतिलिपि लौटा दी, जो ऊपर दिखाए गए कोड का उपयोग करना आसान होगा।

+0

.. क्या आप वाकई एक सबराउटिन कमजोर संदर्भ वापस कर सकते हैं?ऐसा लगता है कि एक subroutine के भीतर बनाया गया कोई भी कमजोर संदर्भ DESTROY-ed होगा जब यह संदर्भ subroutine – Dancrumb

+0

के करीब दायरे से बाहर हो जाता है एक कमजोर संदर्भ परिणाम को एक निहित प्रति में वापस नहीं लौटाएगा (जिसके परिणामस्वरूप एक मजबूत संदर्भ लौटाया जा रहा है)? – Cameron

+2

@ डंक्रंब, @ कैमरॉन, आप एक अधिभारित वस्तु वापस कर सकते हैं जो एक कमजोर संदर्भ संग्रहीत करता है। – ysth

12

जब भी आप किसी नए चर में संदर्भ की प्रतिलिपि बनाते हैं, तो संदर्भ गणना बढ़ जाती है। कमजोर या मजबूत संदर्भ की प्रतिलिपि करते समय यह सच है।

my $obj = {}; # 1 reference to {} stored in $obj 

my $copy = $obj; # 2 references 

weaken $obj;  # 1 reference 
इस बिंदु पर

, $copy क्षेत्र से बाहर जाता है, संदर्भ गिनती शून्य करने के लिए गिर जाएगी, और स्मृति मुक्त हो जाएगा। अब निम्नलिखित कोड मान:

my $newref = $obj; # 2 references 

undef $copy;  # 1 reference 

पर्ल $newref में कमजोर संदर्भ संरक्षित है, तो हैश अप्रत्याशित रूप से dealocated किया जाएगा जब $copy मुक्त कर दिया गया। यह उम्मीद को तोड़ देगा कि जब आप एक संदर्भ की प्रतिलिपि बनाते हैं, तो कम से कम प्रतिलिपि के रूप में यह कम से कम टिकेगा।

संक्षेप में, यदि कमजोर संदर्भ एक असाइनमेंट में बने रहे, तो यह आपको असुरक्षित कमजोरियों के चेक के साथ अपने कोड को कूड़ा करने के लिए मजबूर करेगा, और एक परिवर्तनीय परिवर्तनीय आत्मविश्वास के मुद्दों से बचने के लिए सभी को एक चर को अपनाने के लिए कुछ अन्य तरीकों की आवश्यकता होगी।

संबंधित मुद्दे