2010-08-21 11 views
7

मैंने सोचा कि मुझे नक्शा समझा गया है, हालांकि निम्नलिखित के परिणाम हैं जिन्हें मैं समझ नहीं पा रहा हूं। मुझे पता है कि यह क्यों हो रहा है मैं नहीं जानता कि यह कैसे हो रहा है।

समस्या यह है कि @array की सामग्री बदल रही है क्योंकि $__do_stuff_to_file कॉल के दौरान रीसेट किया जा रहा है। इसलिए मुद्रित किया गया है here: \nhere:\n जब मुझे लगता है कि यह here: donkie\nhere: kong\n हो।

नोट: यह परीक्षण कोड नहीं है। यह सिर्फ मुझे प्रयोगशाला से देखकर याद है। @array की सामग्री क्यों बदल रही है?

यदि मैं $f पर _some_func से 1 लौटने से पहले सेट करता हूं। फिर सरणी अभी भी बरकरार है।

my @array = ("donkie", "kong"); 
map { push @junk, _some_func('blah', $_); } @array; 

if (join ('', @junk) !~ /0/) 
{ # for example sake this is always true since return 1 from _some_func. 
    print map { "here: $_\n"; } @array; 
} 

sub _some_func 
{ # for example sake, lets say $f always exists as a file. 
    my $j = shift; 
    my $f = shift; 
    return 0 if !open(FILE, "< $f"); 
    close FILE; 
    _do_stuff_to_file($f); 

    return 1; 
} 


sub _do_stuff_to_file 
{ 
    my $f = shift; 
    open(IN, "< $f"); 
    open(OUT, "> $f.new"); 

    while (<IN>) 
    { 
     print OUT; 
    } 

    close IN; 
    close OUT; 
} 
+3

आपके प्रश्न में पहले से ही इसका उत्तर है - आपने पहले ही समझाया है कि यह कैसा हो रहा है। क्या आप अपना प्रश्न कुछ ऐसे में बदलना चाहते हैं जैसे "मैं सामान क्लॉबर को $ _' देने से कैसे बचूं? क्योंकि यह एक है जिसे हम उत्तर दे सकते हैं (और माइकल कारमेन ज्यादातर में पहले से ही हैं) – hobbs

+0

मैं सुझावों का सुझाव दिया गया शीर्षक है। @ क्या आप इसे बदलें? – dolmen

उत्तर

9

पर्ल में कई कार्यों डिफ़ॉल्ट चर $_ का उपयोग करें:

यहाँ मैं क्या देख रहा हूँ वर्णन करने के लिए एक उदाहरण के कार्यक्रम है। इनमें से map और रीडलाइन ऑपरेटर <> हैं। foreach की तरह, map लूप वैरिएबल को सूची के प्रत्येक तत्व के लिए एक उपनाम बनाता है। क्या हो रहा है इस लाइन है जो:

while (<IN>) 

$_ को बताए है, जबकि map की अलियासिंग प्रभाव में है। यह $_ (या किसी अन्य वैश्विक चर) का उपयोग करने वाली समस्याओं में से एक है - दूरी पर अजीब कार्रवाई। आप $_ उपयोग करने के लिए जा रहे हैं, यह पहली बार स्थानीय बनाना:

local $_; 
while (<IN>) 
... 

वैकल्पिक रूप से, बजाय एक शाब्दिक चर का उपयोग:

while (my $line = <IN>) 
+0

लेकिन $ _ का उपयोग क्यों सरणी की सामग्री को बदलता है? $ _ सिर्फ एक चर नहीं है जो सरणी के वर्तमान मान की एक प्रति है? – user318747

+0

ठीक है अब मैं देख रहा हूं, धन्यवाद। – user318747

4

$ संशोधित _ अपने प्रारंभिक सरणी बदल जाएगा, क्योंकि $ _ एक उपनाम है वर्तमान तत्व के लिए। आपका कोड इस तरह दिखना चाहिए:

my @array = ("donkie", "kong"); 
my @junk=map {_some_func('blah', $_) } @array; 

if (join ('', @junk) !~ /0/) 
{ # for example sake this is always true since return 1 from _some_func. 
    print map { "here: $_\n"; } @array; 
} 

sub _some_func 
{ # for example sake, lets say $f always exists as a file. 
    my $j = shift; 
    my $f = shift; 
    return 0 if !-e $f; 
    _do_stuff_to_file($f); 
    return 1; 
} 


sub _do_stuff_to_file 
{ 
    my $f = shift; 
    local $_; 
    open(IN, "<",$f); 
    open(OUT, ">", "$f.new"); 

    while (<IN>) 
    { 
     print OUT; 
    } 

    close IN; 
    close OUT; 
} 

पीएस नक्शा रिटर्न सरणी तत्वों की एक ही संख्या के साथ (यदि स्केलर ब्लॉक से वापस आ गया है)। grep केवल उन तत्वों को लौटाता है जिनके लिए ब्लॉक सही है।

+1

सूची 'मानचित्र' रिटर्न इसके इनपुट के रूप में तत्वों की संख्या समान नहीं है। उदाहरण के लिए '@doubled = map {$ _, $ _} (1 .. 5) ' –

0

मैं अलेक्जेंडर और माइकल के उत्तरों को स्वीकार करता हूं: _do_stuff_to_file()$_ का मान बदल रहा है। map$_ के संदर्भ में मैप किए गए तत्व के संग्रहण के लिए सिर्फ एक नाम है, सरणी बदल दी गई है।

अलेक्जेंडर और माइकल _do_stuff_to_file() को बदलने का प्रस्ताव करते हैं, इसलिए वे $_ मान को प्रभावित नहीं करते हैं। बाहरी दायरे को परेशान करने से बचने के लिए $_ जैसे स्थानीय-विशेष विशेष चर के लिए यह अच्छा अभ्यास है।

map { my $x=$_; local $_; push @junk, _some_func('blah', $x); } @array; 

या आम शैली अधिक निम्नलिखित:

समारोह कॉल करने से पहले "तोड़" नक्शा ब्लॉक स्थानीय अनुरूप बनाएं द्वारा अंदर लिंक:

यहाँ एक वैकल्पिक समाधान है कि उस समारोह को छू से बचने के है

@junk = map { my $x=$_; local $_; _some_func('blah', $x) } @array; 
+0

या मानचित्र से पहले' मेरा $ _; 'मानचित्र का उपयोग करने से पहले एक लेक्सिकल $ _, वैश्विक नहीं। (5.10+) – ysth

+0

@ysth "मेरा $ _" नक्शा ब्लॉक में एक नया चर लेक्सिकल बना देगा। लेकिन यह _some_func() और _do_stuff_to_file() संदर्भों को प्रभावित नहीं करेगा, इसलिए यह नहीं होगा समस्या को ठीक करें। – dolmen

+0

हां, यह * उस * मानचित्र के लिए समस्या को ठीक करेगा, जब तक कि आप * चाहते हैं कि वे @array में अलियाकृत मानों को बदलने में सक्षम न हों। – ysth

4

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

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