2011-03-31 19 views
22

क्या था डिजाइन (या तकनीकी) पर्ल स्वचालित रूप से निम्न सिंटैक्स साथ $_ स्थानीयकृत नहीं करने के लिए कारण:पर्ल में, `जबकि (<HANDLE>) {...}` `_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

while (<HANDLE>) {...} 

के रूप में लिखा जाता है कौन सा:

while (defined($_ = <HANDLE>)) {...} 

अन्य निर्माणों कि परोक्ष को लिखने के सब $_ ऐसा स्थानीय तरीके से करें (for/foreach, map, grep), लेकिन while के साथ, आपको स्पष्ट रूप से चर को स्थानीयकृत करना होगा:

local $_; 
while (<HANDLE>) {...} 

मेरा अनुमान है कि कमांड लाइन स्विच के साथ "सुपर-एडब्ल्यूके" मोड में पर्ल का उपयोग करने के साथ इसका कुछ संबंध है, लेकिन यह गलत हो सकता है।

तो अगर कोई जानता है (या भाषा डिजाइन चर्चा में अभी तक बेहतर था), तो क्या आप हमारे साथ इस व्यवहार के पीछे तर्क साझा कर सकते हैं? अधिक विशेष रूप से, बग के बाहर $_ के मूल्य को रोकने के लिए क्यों अनुमति दी जा रही थी, बग के कारण यह महत्वपूर्ण हो सकता है (जो मुझे एसओ और अन्य पर्ल कोड में सभी जगहों पर देखता है)?


मामले में यह ऊपर से स्पष्ट नहीं है, कारण है कि $_while साथ स्थानीय जाना चाहिए कि इस उदाहरण में दिखाया गया है:

sub read_handle { 
    while (<HANDLE>) { ... } 
} 

for (1 .. 10) { 
    print "$_: \n"; # works, prints a number from 1 .. 10 
    read_handle; 
    print "done with $_\n"; # does not work, prints the last line read from 
           # HANDLE or undef if the file was finished 
} 
+3

यही कारण है कि मैं (लगभग) कभी भी $ _ पर भरोसा नहीं करता हूं। –

+0

यही कारण है कि मैं कभी भी पर्ल का उपयोग नहीं करता हूं। – kurumi

+0

मुझे लगता है कि आपका मतलब है * {स्थानीय $ _; जबकि () {...}} * – MkV

उत्तर

14
thread से perlmonks.org पर

:

foreach और while के बीच एक अंतर है क्योंकि वे दो पूरी तरह सेहैंविभिन्न चीजें। foreach हमेशा एक चर पर लूप करते समय एक चर को असाइन करता है, जबकि while सामान्यतः नहीं करता है। यह सिर्फ while (<>) एक अपवाद है और केवल एकल हीरा ऑपरेटर होने पर $_ पर निहित असाइनमेंट है।

और यह भी:

एक क्यों while(<>) परोक्ष अपना जादू की भाग के रूप में $_ स्थानीय बनाना नहीं है के लिए संभावित कारण है कि कभी कभी आप पाश बाहर $_ का अंतिम मान उपयोग करना चाहते ।

+0

'और भी', यह इस मुद्दे का क्रूक्स है, हालांकि, उस व्यवहार को उन बगों को न्यायसंगत साबित करने के लिए पर्याप्त क्यों समझा गया था। व्यक्तिगत रूप से मुझे लूप से परे बने रहने के लिए '$ _' के मूल्य की आवश्यकता नहीं है, लेकिन अवसर पर 'स्थानीय $ _' को भूलकर काट दिया गया है। –

7

काफी आसानी से, while कभी भी स्थानीय नहीं। कोई चर while निर्माण से जुड़ा हुआ नहीं है, इसलिए इसमें स्थानीयकरण के लिए कुछ भी नहीं है।

यदि आप while लूप अभिव्यक्ति में या while लूप बॉडी में कुछ चर बदलते हैं, तो यह आपकी ज़िम्मेदारी है कि इसे पर्याप्त रूप से गुंजाइश करें।

+0

कोई वैरिएबल 'while' निर्माण से जुड़ा हुआ नहीं है, लेकिन निश्चित रूप से' जबकि () 'निर्माण से जुड़ा हुआ है। मुझे लगता है कि यह पेफोल ऑप्टिमाइज़र को समायोजित करने जितना सरल होगा जो '{स्थानीय $ _ उत्पन्न करने के लिए' 0 () 'को फिर से लिखता है; जबकि (परिभाषित ($ _ = )) {...}} ' –

+0

@ एरिक स्ट्रॉम, मैं उस समाधान के साथ किसी भी समस्या के बारे में नहीं सोच सकता - यह स्कोपिंग, अगली/आखिरी/फिर से या अपवादों को तोड़ नहीं देता है - - लेकिन मुझे लगता है कि ऑप्टिमाइज़र को 'जबकि (<$fh>) '(जिसे स्थानीयकरण करना चाहिए) और' (परिभाषित ($ _ = <$fh>)) के बीच ऑप्टिमाइज़र को डिस्टिंगिज़ की अनुमति देने के लिए कुछ प्रमुख परिवर्तनों की आवश्यकता होगी। (जो नहीं होना चाहिए)। – ikegami

2

अटकलें: क्योंकि for और foreach मूल्यों पर इटरेटर और लूप हैं, जबकि while एक शर्त पर काम करता है। while (<FH>) के मामले में स्थिति यह है कि फ़ाइल को डेटा से पढ़ा गया था। <FH>$_ पर लिखता है, while नहीं। अंतर्निहित defined() परीक्षण बेकार मूल्य को पढ़ने पर लूप को समाप्त करने से निष्क्रिय कोड को रोकने के लिए केवल एक affordance है।

while लूप के अन्य रूपों के लिए, उदा। while (/foo/) आप $_ को स्थानीयकृत करना चाहते हैं।

जबकि मैं मानता हूँ कि यह अच्छा होगा अगर while (<FH>) स्थानीय $_, यह एक बहुत विशेष मामला है, जो जब यह गति प्रदान करने के पहचानने और जब साथ अन्य समस्याओं का कारण बन सकता होना चाहिए था नहीं करने के लिए, बहुत <EXPR> विशिष्ठ के लिए नियमों की तरह हैंडल पढ़ना या glob पर कॉल करना।

0

एक साइड नोट के रूप में, हम केवल while(<$fh>) लिखते हैं क्योंकि पर्ल में असली इटरेटर नहीं हैं। यदि पर्ल के पास उचित इटरेटर थे, <$fh> एक लौटाएगा। for उस फ़ाइल को एक सरणी में पूरी फ़ाइल को स्लिप करने के बजाय एक समय में एक लाइन को फिर से चलाने के लिए उपयोग करेगा। while(<$fh>) या इसके साथ जुड़े विशेष मामलों की कोई आवश्यकता नहीं होगी।