2010-06-17 15 views
5

दो अलग हैश एक सूची में संदर्भित अंदर एक precompiled regex लाना:पर्ल सूचियों के अंदर संदर्भ क्यों संकलित किए गए हैं?

my @list =(); 

my $regex = qr/ABC/; 

push @list, { 'one' => $regex }; 
push @list, { 'two' => $regex }; 

use Data::Dumper; 
print Dumper(\@list); 

मैं उम्मीद थी:

$VAR1 = [ 
     { 
     'one' => qr/(?-xism:ABC)/ 
     }, 
     { 
     'two' => qr/(?-xism:ABC)/ 
     } 
    ]; 

लेकिन बजाय हम एक परिपत्र संदर्भ मिलता है:

$VAR1 = [ 
     { 
     'one' => qr/(?-xism:ABC)/ 
     }, 
     { 
     'two' => $VAR1->[0]{'one'} 
     } 
    ]; 

यह अनिश्चित काल तक नेस्टेड हैश संदर्भों के साथ होगा और उथल-पुथल $regex की प्रतिलिपि बनाई जाएगी।

मुझे लगता है कि मूल कारण यह है कि प्रीकंपिल्ड रेगेक्स वास्तव में संदर्भ हैं, और उसी सूची संरचना के अंदर संदर्भ एक अनुकूलन के रूप में संकलित किए जाते हैं (\ $ स्केलर वैसे ही व्यवहार करता है)। मैं पूरी तरह से ऐसा करने की उपयोगिता को पूरी तरह से नहीं देखता (संभवतः किसी संदर्भ के संदर्भ में एक ही स्मृति पदचिह्न है), लेकिन हो सकता है कि आंतरिक प्रतिनिधित्व

पर आधारित कोई कारण है, क्या यह सही व्यवहार है? क्या मैं इसे होने से रोक सकता हूं? शायद जीसी को और अधिक कठिन बनाने के अलावा, इन परिपत्र संरचनाएं गंभीर गंभीर सिरदर्द बनाती हैं। उदाहरण के लिए, कभी-कभी एक ही नियमित अभिव्यक्ति वाले प्रश्नों की सूची में पुनरावृत्ति करने से मोंगोडीबी चालक को एक बुरा सीगफॉल्ट (https://rt.cpan.org/Public/Bug/Display.html?id=58500 देखें)

+0

यह परिपत्र कैसा है? – Ether

+1

qr/$ regex/एक नया बना देगा, जैसा कि Storable :: dclone होगा। – ysth

+0

ईथर: मैं डेटा :: डम्पर आउटपुट की गलत व्याख्या कर रहा था क्योंकि समानांतर (और वास्तविक) परिपत्र संदर्भ त्रुटि आई थी, उपरोक्त सीपीएन थ्रेड –

उत्तर

9

यह अपेक्षित व्यवहार है।

आपका संदर्भ वास्तव में परिपत्र नहीं है; आपके पास दो अलग-अलग आइटम हैं जो एक ही चीज़ को इंगित करते हैं। डेटा :: डम्पर एक मानव-पठनीय, स्मृति में आपके डेटा संरचनाओं का पर्ल-पारदर्शी प्रतिनिधित्व प्रिंट कर रहा है, और इसका वास्तव में क्या अर्थ है कि $list[0]->{one} और $list[1]->{two} दोनों एक ही चीज़ पर इंगित करते हैं।

पर्ल संदर्भ-गिनती कचरा संग्रह का उपयोग करता है, और यह परिपत्र डेटा संरचनाओं के साथ परेशानी में पड़ सकता है, यह डेटा संरचना कोई विशेष समस्या प्रस्तुत नहीं करती है।

+0

डेटा :: डूपर पेज को देखकर आप सही हैं, '\ $ सूची [1] -> {दो} 'एक परिपत्र संदर्भ होगा लेकिन' $ सूची [1] -> {दो} 'नहीं है। यह मोंगोडीबी दुर्घटना व्यवहार को और अधिक रहस्यमय बनाता है (हालांकि एक स्वतंत्र बग है जहां एक क्वेरी में एक स्पष्ट सर्कुलर संदर्भ segfaults perl है, ऊपर आरटी लिंक देखें)। –

+0

नज़दीकी निरीक्षण पर, मोंगो()/डबल-फ्री() त्रुटि मैंने मोंगो के साथ देखा था, शायद अनजाने में कई फोर्क प्रक्रियाओं में एक कनेक्शन ऑब्जेक्ट साझा कर रहा था। मुझे सही दिशा में इंगित करने के लिए धन्यवाद, (असंबद्ध) परिपत्र संदर्भ मुद्दे वास्तव में मुझे ऊपर फिसल गया। –

6

यहां कुछ भी मजाकिया नहीं हो रहा है।

  1. आपने उसी डेटा संरचना में दो बार समान संदर्भ संग्रहीत किया है।
  2. फिर आपने उस संरचना के प्रतिनिधित्व को मुद्रित करने के लिए डेटा :: डम्पर से पूछा।
  3. डेटा :: डम्पर उस डेटा को राउंडट्रिप करना चाहता है जिसे आप इसे यथासंभव ईमानदारी से देते हैं, जिसका अर्थ है कि इसे पर्ल कोड आउटपुट करने की आवश्यकता है जो डेटा संरचना उत्पन्न करेगी जिसमें $list[0]{one} पर एक ही संदर्भ शामिल है क्योंकि यह $list[0]{two} पर है।
  4. यह डेटा संरचना को आउटपुट करके करता है जहां एक सदस्य को उसी संरचना के किसी अन्य सदस्य का संदर्भ होता है।
  5. लेकिन यह वास्तव में एक परिपत्र संदर्भ नहीं है।
1

मैं मूल कारण यह सोचते हैं रहा है कि precompiled regexes वास्तव में संदर्भ हैं, और एक ही सूची संरचना के भीतर उसका संदर्भ अनुकूलन (\ $ अदिश उसी तरह बर्ताव करता है) के रूप में जमा हो रहा है।मैं पूरी तरह से (एक ही स्मृति पदचिह्न है एक संदर्भ के लिए संभवतः एक संदर्भ) ऐसा करने का उपयोगिता नहीं दिख रहा है, लेकिन शायद वहाँ एक कारण आंतरिक प्रतिनिधित्व पर आधारित

कारण यह है कि है यह किसी डेटा संरचना का संदर्भ हो सकता है जिसे कहीं भी घोंसला में शीर्ष स्तर (लूप) पर संदर्भ दिया जाता है। अगर यह ऐसी संरचना में जारी रहा तो यह एक अनंत लूप बनाएगा। जिस तरह से यह इससे बचाता है, वह कभी भी पहले से देखे गए संदर्भ में पुन: साझा नहीं करना है, इसलिए इसके बजाय यह प्रिंट करता है कि यह पहले से ही इसे देख चुका है और आपको पिछले मुद्रित स्थान पर संदर्भित करता है।

इस मामले में कोई लूप नहीं है, लेकिन डेटा :: डम्पर के पास यह जानने का कोई तरीका नहीं है कि इससे पहले कि यह ढांचे में फिर से हो जाए, यह बहुत देर हो चुकी है।

इस तरह के एक स्केलर के लिए ऐसा करने के लिए शायद आवश्यक नहीं है, लेकिन शायद ऐसा होता है क्योंकि डेटा :: डूपर जांचता है कि यह प्रकार की जांच करने से पहले संदर्भ को पहले से ही देखा गया है या नहीं। यह लाभ भी देता है जो यह दिखाता है कि यह एक ही डेटा का संदर्भ है, इसकी एक प्रति नहीं, जो शायद उपयोगी जानकारी है जो खो जाएंगी यदि यह सिर्फ मूल्य मुद्रित करे।

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