2010-01-26 29 views
29

मैं निराश हूं। ठीक है, तो यह शायद सबसे अधिक मजेदारPerl बग मैंने कभी पाया है। आज भी मैं पर्ल के बारे में नई चीजें सीख रहा हूं। अनिवार्य रूप से, फ्लिप फ्लॉप ऑपरेटर .. जो रिटर्न झूठी तक दाएँ हाथ की ओर लौटता है झूठी वैश्विक राज्य रखने के (या कि क्या है जब तक बाएं हाथ की ओर सच, और फिर सच रिटर्न मैं मान लें।)क्या पर्ल की फ्लिप-फ्लॉप ऑपरेटर बग है? इसमें वैश्विक स्थिति है, मैं इसे कैसे रीसेट कर सकता हूं?

क्या मैं इसे रीसेट कर सकता हूं (शायद यह पर्ल   4-एस्क्यू के लिए शायद ही कभी अच्छा होगा reset())? या, इस ऑपरेटर को सुरक्षित रूप से उपयोग करने का कोई तरीका नहीं है?

मुझे यह भी नहीं देखा गया है (वैश्विक संदर्भ बिट) perldoc perlop में कहीं भी दस्तावेज है क्या यह एक गलती है?

कोड

use feature ':5.10'; 
use strict; 
use warnings; 

sub search { 
    my $arr = shift; 
    grep { !(/start/ .. /never_exist/) } @$arr; 
} 

my @foo = qw/foo bar start baz end quz quz/; 
my @bar = qw/foo bar start baz end quz quz/; 

say 'first shot - foo'; 
say for search \@foo; 

say 'second shot - bar'; 
say for search \@bar; 

बिगाड़ने

$ perl test.pl 
first shot 
foo 
bar 
second shot 
+2

अच्छा सवाल! ऐसा लगता है कि यह बंद होने की तरह अभिनय करता है। – Demosthenex

+0

ओह मुझे यह सामना करना पड़ा - मैंने फ्लिपफ्लोप का उपयोग करके एक फ़ंक्शन लिखा, जिसे इसे दो बार कहा जाता है और दूसरी बार इसे पहले से संरक्षित किया गया था। मेरा ऐप तोड़ दिया! –

+2

वाह, मुझे कभी भी 'रीसेट' अस्तित्व में नहीं पता था। ++ बस इसके लिए। :) – friedo

उत्तर

34

क्या कोई स्पष्टीकरण दे सकता है कि दस्तावेज के साथ समस्या क्या है? यह स्पष्ट रूप से इंगित करता है:

Each ".." operator maintains its own boolean state. 

वहाँ वहाँ के बारे में क्या "प्रत्येक" का अर्थ है कुछ अस्पष्टता है, लेकिन मुझे नहीं लगता कि प्रलेखन अच्छी तरह से एक जटिल स्पष्टीकरण द्वारा कार्य किया जाएगा है।

ध्यान दें कि पर्ल के अन्य इटरेटर (each या स्केलर संदर्भ glob) एक ही समस्या का कारण बन सकते हैं। चूंकि each के लिए राज्य किसी विशेष हैश के लिए बाध्य है, कोड का एक विशेष बिट नहीं, each हैश पर भी keys पर कॉल करके रीसेट किया जा सकता है। लेकिन glob या .. के लिए, रीसेट होने तक इटरेटर को कॉल करके सिवाय कोई रीसेट तंत्र उपलब्ध नहीं है। एक नमूना ग्लोब बग:

sub globme { 
    print "globbing $_[0]:\n"; 
    print "got: ".glob("{$_[0]}")."\n" for 1..2; 
} 
globme("a,b,c"); 
globme("d,e,f"); 
__END__ 
globbing a,b,c: 
got: a 
got: b 
globbing d,e,f: 
got: c 
Use of uninitialized value in concatenation (.) or string at - line 3. 
got: 

ज्यादा उत्सुक के लिए, यहाँ कुछ उदाहरण हैं जहां स्रोत में एक ही .. एक अलग .. ऑपरेटर है:

अलग बंद:

sub make_closure { 
    my $x; 
    return sub { 
     $x if 0; # Look, ma, I'm a closure 
     scalar($^O..!$^O); # handy values of true..false that don't trigger ..'s implicit comparison to $. 
    } 
} 
print make_closure()->(), make_closure()->(); 
__END__ 
11 

$x if 0 लाइन पर टिप्पणी करने के लिए टिप्पणी करें कि गैर-बंद होने के लिए एक ही .. ऑपरेशन 12 आउटपुट के साथ सभी "प्रतियां" द्वारा साझा किया गया है।

धागे:

use threads; 
sub coderef { sub { scalar($^O..!$^O) } } 
coderef()->(); 
print threads->create(coderef())->join(), threads->create(coderef())->join(); 
__END__ 
22 

थ्रेडेड कोड के साथ शुरू होता है जो कुछ भी की स्थिति .. धागा निर्माण से पहले किया गया था, लेकिन सूत्र में अपने राज्य में परिवर्तन और कुछ को प्रभावित करने से अलग कर रहे हैं।

Recursion:

sub flopme { 
    my $recurse = $_[0]; 
    flopme($recurse-1) if $recurse; 
    print " "x$recurse, scalar($^O..!$^O), "\n"; 
    flopme($recurse-1) if $recurse; 
} 
flopme(2) 
__END__ 
1 
1 
2 
    1 
3 
2 
4 

प्रत्यावर्तन के प्रत्येक गहराई एक अलग .. ऑपरेटर है।

+2

+1 - अलग बंद करने का विचार पसंद है। – mob

+1

ysth ++ आपका उत्तर सुंदर और बढ़िया है। यही वह है जिसकी तलाश में मैं हूं। धन्यवाद। –

7

"सीमा ऑपरेटर" .. "रेंज ऑपरेटर्स 'के तहत perlop में प्रलेखित है। Doucmentation के माध्यम से देखकर, ऐसा प्रतीत होता है कि .. ऑपरेटर की स्थिति को रीसेट करने का कोई तरीका नहीं है। .. ऑपरेटर का प्रत्येक उदाहरण अपने राज्य रखता है, जिसका अर्थ है कि किसी विशेष .. ऑपरेटर की स्थिति का संदर्भ देने का कोई तरीका नहीं है।

ऐसा लगता है कि यह इस तरह के रूप में बहुत छोटे स्क्रिप्ट के लिए डिज़ाइन किया गया है दिखता है:

if (101 .. 200) { print; } 

प्रलेखन कहा गया है कि इस बात के लिए

if ($. == 101 .. $. == 200) { print; } 

कम है किसी तरह $. के उपयोग वहाँ निहित है (toolic अंक बाहर एक टिप्पणी में कि यह भी दस्तावेज है)। ऐसा लगता है कि यह लूप एक बार ($. == 200 तक) पर्ल दुभाषिया के दिए गए उदाहरण में चलता है, और इसलिए आपको .. फ्लिप-फ्लॉप की स्थिति को रीसेट करने की चिंता करने की आवश्यकता नहीं है।

यह ऑपरेटर आपके द्वारा पहचाने गए कारणों के लिए, अधिक सामान्य पुन: प्रयोज्य संदर्भ में बहुत उपयोगी प्रतीत नहीं होता है।

+0

दस्तावेज़ों से उद्धरण: "यदि या तो स्केलर का संचालन .. एक निरंतर अभिव्यक्ति है, तो ऑपरेंड को सही माना जाता है यदि यह वर्तमान इनपुट लाइन संख्या ($। चर) के बराबर (==) है।" 101 और 202 निरंतर अभिव्यक्ति दोनों हैं। – toolic

+0

ठीक है, मैंने दस्तावेज़ों में नहीं देखा था 'जहां ऑपरेटर के वैश्विक संदर्भ का उल्लेख किया गया था' - जबकि मैंने 'perldoc perlop' का उल्लेख किया, मैंने भ्रम के लिए पर्याप्त डॉक-प्रश्न को अर्हता प्राप्त नहीं की। –

2

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

+0

यह शायद दस्तावेज़ीकरण में स्पष्ट किया जाना चाहिए। * पोक ब्रायन डी फोय * – Ether

+0

मैं कल एक डॉक्टर पैच जमा कर सकता हूं, लेकिन ऐसा लगता है कि यह 'ग्लोबल' बनाने के लिए पर्लिंग पैच द्वारा बेहतर तय किया गया था, और संभवतः 'रीसेट() ' –

+1

I के साथ रीसेट कर दिया गया था। पर्लोप के लिए एक बहुत ही छोटा नोट जोड़ा, लेकिन मैंने सोचा कि यह पहले स्पष्ट था। समस्या तब होती है जब आप उन चीज़ों में पढ़ते हैं जो वहां नहीं हैं, जैसे कि यह कहता है कि यह कुछ भी नहीं कहता है। –

1

.. ऑपरेटर का प्रत्येक उपयोग अपना स्वयं का राज्य बनाए रखता है। एलेक्स ब्राउन की तरह, जब आप समारोह छोड़ते हैं तो आपको इसे झूठी स्थिति में छोड़ना होगा।हो सकता है आप की तरह कुछ कर सकता है:

sub search { 
    my $arr = shift; 
    grep { !(/start/ || $_ eq "my magic reset string" .. 
      /never_exist/ || $_ eq "my magic reset string") } 
     (@$arr, "my magic reset string"); 
} 
+0

मैं 'उपयोग' शब्द का उपयोग नहीं करता। मुझे लगता है कि 'स्रोत में उपस्थिति' –

+2

@Evan कैरोल कहने के लिए यह अधिक सटीक है: यह कहां गलत है इसके लिए मेरा उत्तर देखें। – ysth

+0

हाँ हाँ, आप स्पष्ट रूप से बेहतर perl'er महान पोस्ट हैं। (मैंने धागे का अनुमान लगाया होगा) –

7

का संभावित हल/हैक/निवारण हेतु धोखा अपने सरणी के अंत मूल्य संलग्न करने के लिए है:

sub search { 
    my $arr = shift; 
    grep { !(/start/ .. /never_exist/) } @$arr, 'never_exist'; 
} 

यह गारंटी देगा कि सीमा ऑपरेटर की आरएचएस अंततः सच हो जाएगा।

बेशक, यह किसी भी तरह का सामान्य समाधान नहीं है।

मेरी राय में, यह व्यवहार स्पष्ट रूप से प्रलेखित नहीं है। यदि आप एक स्पष्ट स्पष्टीकरण बना सकते हैं, तो आप पर perlbug के माध्यम से पैच लागू कर सकते हैं।

+0

यह निश्चित रूप से एक साधारण वैध कामकाज (एक व्यवहार्य समाधान) है, और मैंने इस प्रश्न पर सभी उत्तरों को वोट दिया। लेकिन, वर्तमान में मैं ऑपरेटर के बारे में और जानना चाहता हूं। –

+3

या इसे पहले स्थान पर सरणी पर धक्का न दें: 'grep {! (/ Start/../never_exist /)} (@ $ arr,' never_exist '); ' –

+0

@ ब्रायन/डेव: हाँ, मैं लापरवाह था। मैंने कोड अपडेट किया है। – toolic

18

चाल उसी flip-flop का उपयोग नहीं करती है, इसलिए आपके पास चिंता करने की कोई स्थिति नहीं है। बस एक नया फ्लिप फ्लॉप है कि आप केवल एक बार उपयोग के साथ आप एक नया सबरूटीन देने के लिए एक जनरेटर समारोह बनाने:

sub make_search { 
    my($left, $right) = @_; 
    sub { 
     grep { !(/\Q$left\E/ .. /\Q$right\E/) } @{$_[0]}; 
     } 
} 

my $search_sub1 = make_search('start', 'never_existed'); 
my $search_sub2 = make_search('start', 'never_existed'); 


my @foo = qw/foo bar start baz end quz quz/; 

my $count1 = $search_sub1->(\@foo); 
my $count2 = $search_sub2->(\@foo); 

print "count1 $count1 and count2 $count2\n"; 

मैं भी Make exclusive flip-flop operators में इस बारे में लिखें।