2009-02-13 10 views
14

मेरे पास पर्ल में अक्सर एक सबराउटिन होता है जो कुछ जानकारी के साथ एक सरणी भरता है। जब से मैं भी सी ++ में हैकिंग करने के लिए इस्तेमाल कर रहा हूँ, मुझे लगता है अपने आप को अक्सर पर्ल में इस तरह करते हैं, संदर्भों का उपयोग:एक पर्ल सबराउटिन अक्षम से एक संपूर्ण सरणी लौट रहा है?

my @array; 
getInfo(\@array); 

sub getInfo { 
    my ($arrayRef) = @_; 
    push @$arrayRef, "obama"; 
    # ... 
} 
और अधिक सरल संस्करण के बजाय

:

my @array = getInfo(); 

sub getInfo { 
    my @array; 
    push @array, "obama"; 
    # ... 
    return @array; 
} 

कारण की बेशक, मैं नहीं चाहता कि सरणी को सबराउटिन में स्थानीय रूप से बनाया जाए और फिर बदले में कॉपी किया जाए।

क्या यह सही है? या पर्ल अनुकूलित है कि वैसे भी दूर?

+0

हो सकता है कि आप एक उच्च स्तर पर समझा सकें जो आप करने की कोशिश कर रहे हैं। जो भी आप चाहते हैं उसे लिखने का एक और आधुनिक, पर्लिश तरीका हो सकता है जो आपकी समस्या से पूरी तरह से बच जाएगा। या कम से कम अपने इरादे को और स्पष्ट करें। –

+0

@ अज्ञात (गूगल): मैं इसे अक्सर अलग-अलग संदर्भों में करता हूं। पिछली बार जब मैं एक सरणी में एक फाइल पढ़ना चाहता था। तो फ़ाइल को खोला जाना है, मैं एसटीडीईआरआर पर कौन सी फाइल खोल रहा हूं, इस बारे में जानकारी प्रिंट करता हूं, लाइनों को थोड़ा सा संशोधित करता हूं और उन्हें सरणी पर दबाता हूं, फिर फ़ाइल बंद कर देता हूं। – Frank

+0

कैसे संशोधित करें? जैसे मैप स्टेटमेंट के साथ प्रति लाइन किया जा सकता है? मुझे फिर से अन्य तकनीकों के पक्ष में, अत्यधिक संदिग्ध होने के लिए किसी सरणी पर कुछ धक्का लग रहा है। कभी-कभी इसकी मदद नहीं की जा सकती है, हालांकि –

उत्तर

18

पहली जगह में एक सरणी संदर्भ लौटने के बारे में क्या?

sub getInfo { 
    my $array_ref = []; 
    push @$array_ref, 'foo'; 
    # ... 
    return $array_ref; 
} 

my $a_ref = getInfo(); 
# or if you want the array expanded 
my @array = @{getInfo()}; 

संपादित dehmann की टिप्पणी के अनुसार:

यह भी समारोह में एक सामान्य सरणी का उपयोग करें और इसे करने के लिए एक संदर्भ के वापस जाने के लिए संभव है।

sub getInfo { 
    my @array; 
    push @array, 'foo'; 
    # ... 
    return \@array; 
}  
+0

यह मेरे लिए सबसे अच्छा समाधान की तरह लगता है! – Powerlord

+0

दरअसल, फ़ंक्शन में वास्तविक सरणी बनाने के बारे में, लेकिन इसे इसके संदर्भ में वापस लाने के बारे में कैसे? पर्ल स्थानीय रूप से बनाए गए सरणी को जीवित रखेगा और एक संदर्भ को कुशलता से वापस कर देगा। – Frank

+0

@ डेहमान: अच्छा बिंदु, मैंने आपकी टिप्पणी में आपका टिप्पणी शामिल किया, धन्यवाद। – user55400

-4

मुझे पर्ल के बारे में कुछ नहीं पता है, इसलिए यह एक भाषा-तटस्थ उत्तर है।

यह एक अर्थ में, एक सबराउटिन से कॉलिंग प्रोग्राम में एक सरणी की प्रतिलिपि बनाने में अक्षम है। अक्षमता अतिरिक्त स्मृति में उत्पन्न होती है और डेटा को एक स्थान से दूसरे स्थान पर कॉपी करने के लिए लिया जाता है। दूसरी तरफ, सबसे बड़े सरणी के लिए, आप शायद एक लानत न दें, और लालित्य, कसने या किसी अन्य कारण के लिए सरणी को कॉपी करना पसंद कर सकते हैं।

कॉलिंग प्रोग्राम को सरणी के पते को पास करने के लिए उपरोक्त के लिए कुशल समाधान है। जैसा कि मैंने कहा, मुझे इस संबंध में पर्ल के डिफ़ॉल्ट व्यवहार के बारे में कोई जानकारी नहीं है। लेकिन कुछ भाषाएं प्रोग्रामर को कौन सा दृष्टिकोण चुनने का विकल्प प्रदान करती हैं।

+0

पर्ल में "सरणी का पता" एक संदर्भ है। सवाल यह है कि क्या पर्ल इसके लिए अनुकूलित करता है। –

13

उत्तीर्ण संदर्भ अधिक कुशल है, लेकिन अंतर सी ++ में जितना बड़ा नहीं है। तर्क स्वयं मानता है (जिसका अर्थ है: सरणी में मान) हमेशा संदर्भ द्वारा पारित होते हैं (लौटाए गए मूल्यों की प्रतिलिपि बनाई जाती है)।

प्रश्न है: क्या इससे कोई फर्क पड़ता है? ज्यादातर समय, यह नहीं करता है। यदि आप 5 तत्व लौट रहे हैं, तो इसके बारे में परेशान न करें। यदि आप 100'000 तत्वों को वापस/पास कर रहे हैं, तो संदर्भों का उपयोग करें। अगर यह एक बाधा है तो केवल इसे अनुकूलित करें।

3

अंतिम रोमिनेशन का जवाब देने के लिए, नहीं, पर्ल इसे अनुकूलित नहीं करता है। यह वास्तव में नहीं, क्योंकि एक सरणी लौटने और एक स्केलर लौटने के लिए मूल रूप से अलग हैं।

यदि आप बड़ी मात्रा में डेटा से निपट रहे हैं या यदि प्रदर्शन एक प्रमुख चिंता है, तो आपकी सी आदतें आपको अच्छी तरह से पास करने और संरचनाओं के बजाय डेटा संरचनाओं के संदर्भ वापस कर देगी ताकि उन्हें आवश्यकता न हो कॉपी करने के लिए। लेकिन, जैसा कि लियोन टिमर्मन ने इंगित किया था, उस समय के विशाल बहुमत, आप डेटा की थोड़ी मात्रा से निपट रहे हैं और प्रदर्शन इतना बड़ा सौदा नहीं है, इसलिए इसे किसी भी तरह से सबसे अधिक पठनीय लगता है।

8

अगर मैं अपने उदाहरण को देखो और क्या आप मुझे इस तरह से इसे लिखने के लिए प्रयोग किया जाता रहा हूँ क्या करना चाहते हैं के बारे में सोचना:

sub getInfo { 
    my @array; 
    push @array, 'obama'; 
    # ... 
    return \@array; 
} 

यह सीधा संस्करण के रूप में मुझे लगता है कि जब मैं बड़ी वापसी की जरूरत है डाटा की मात्रा। सरणी को sub के बाहर आवंटित करने की आवश्यकता नहीं है जैसा कि आपने अपने पहले कोड स्निपेट में लिखा था क्योंकि my यह आपके लिए करता है। वैसे भी आपको Leon Timmermanssuggest के रूप में समयपूर्व अनुकूलन नहीं करना चाहिए।

2

इस तरह से मैं आम तौर पर एक सरणी वापस करूँगा।

sub getInfo { 
    my @array; 
    push @array, 'foo'; 
    # ... 
    return @array if wantarray; 
    return \@array; 
} 

इस तरह यह, जिस तरह से आप चाहते हैं काम करेंगे अदिश, या सूची संदर्भों में।

my $array = getInfo; 
my @array = getInfo; 

$array->[0] == $array[0]; 

# same length 
@$array == @array; 

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

+0

फिर आप getInfo() को स्केलर मान में असाइन करके गिनती नहीं प्राप्त कर सकते हैं। http://perlmonks.org/?node_id=729965 में वांछित के उपयोग के बारे में एक दिलचस्प बहस है। – daotoad

+0

मैं मानता हूं, मैंने लगभग तीन साल पहले 'वांछरे' का उपयोग करने के लिए उपयोग किया था। मुझे मुश्किल थी यह अच्छी सुविधा है। कई अलग-अलग कुशल डेवलपर्स के साथ बड़े पर्ल प्रोजेक्ट में कई वर्षों के अनुभव के बाद मैंने निर्णय लिया है कि संदर्भ जागरूकता कोड पर्ल में सबसे बुरी चीज में से एक है। –

+1

@daotoad: आप कभी भी यह नहीं मान सकते कि सूची संदर्भ में एक सूची लौटने वाला फ़ंक्शन स्केलर संदर्भ में इसकी लंबाई लौटाएगा, क्योंकि यह तब होता है जब फ़ंक्शन एक सरणी देता है। यदि फ़ंक्शन एक सूची मान देता है, तो आपको सूची का अंतिम तत्व प्राप्त होगा। क्यूं कर? क्योंकि पर्ल आपको देखता है। :) –

2

दो विचार हैं। स्पष्ट एक यह है कि आपकी सरणी कितनी बड़ी होगी? यदि यह कुछ दर्जन तत्वों से कम है, तो आकार एक कारक नहीं है (जब तक कि आप कुछ तेजी से बुलाए गए फ़ंक्शन के लिए माइक्रो-ऑप्टिमाइज़िंग नहीं कर लेते हैं, लेकिन आपको इसे साबित करने के लिए कुछ मेमोरी प्रोफाइलिंग करना होगा)।

यह आसान हिस्सा है। अनदेखा दूसरा विचार इंटरफ़ेस है। लौटाए गए सरणी का उपयोग कैसे किया जा रहा है? यह महत्वपूर्ण है क्योंकि पर्ल में पूरी सरणी डीरफ्रेंसिंग थोड़ी भयानक है। उदाहरण के लिए:

for my $info (@{ getInfo($some, $args) }) { 
    ... 
} 

यह बदसूरत है। यह काफी बेहतर है।

for my $info (getInfo($some, $args)) { 
    ... 
} 

यह खुद को मानचित्रण और पकड़ने के लिए भी उधार देता है।

my @info = grep { ... } getInfo($some, $args); 

लेकिन एक सरणी रेफरी लौटने सुविधाजनक हो सकता है यदि आप अलग-अलग तत्वों बाहर लेने के लिए जा रहे हैं:

my $address = (getInfo($some, $args))[2]; 

या::

my @info = getInfo($some, $args); 
my $address = $info[2]; 
कि तुलना में आसान है

my $address = getInfo($some, $args)->[2]; 

लेकिन उस बिंदु पर, आप sho उल सवाल है कि @info वास्तव में एक सूची है या हैश है।

my $address = getInfo($some, $args)->{address}; 

आपको नहीं करना चाहिए क्या getInfo() है अदिश संदर्भ में एक सरणी रेफरी और सूची संदर्भ में एक सरणी वापसी है। यह स्केलर संदर्भ के पारंपरिक उपयोग को सरणी लंबाई के रूप में जोड़ता है जो उपयोगकर्ता को आश्चर्यचकित करेगा।

अंत में, मैं अपना खुद का मॉड्यूल, Method::Signatures प्लग करूंगा, क्योंकि यह सरणी संदर्भ वाक्य में उपयोग किए बिना सरणी संदर्भों में गुजरने के लिए एक समझौता प्रदान करता है।

use Method::Signatures; 

method foo(\@args) { 
    print "@args";  # @args is not a copy 
    push @args, 42; # this alters the caller array 
} 

my @nums = (1,2,3); 
Class->foo(\@nums); # prints 1 2 3 
print "@nums";  # prints 1 2 3 42 

यह Data::Alias के जादू के माध्यम से किया जाता है।

+0

आप कभी भी यह नहीं मान सकते कि सूची संदर्भ में एक सूची लौटने वाला फ़ंक्शन स्केलर संदर्भ में इसकी लंबाई लौटाएगा, क्योंकि यह तब होता है जब फ़ंक्शन एक सरणी देता है।यदि फ़ंक्शन एक गैर-सरणी सूची मान देता है, तो आपको इसके आकार के बजाय सूची का अंतिम तत्व प्राप्त होगा। –

+0

फिर सूचियां वापस न करें! यदि आपका हथौड़ा संभाल आपको स्प्लिंटर्स देता है, तो दस्ताने पहनें, इसे चिकनी बनाएं! पर्ल 5 में पूरी "सूची बनाम सरणी" चीज खेल के मैदान के बीच में एक विशाल, अंतरंग भालू जाल है। – Schwern

+0

मैं पूरी तरह से आपकी अंतिम वाक्य से सहमत हूं। मैं जोड़ूंगा कि खेल के मैदान में अधिकांश बच्चे, और यहां तक ​​कि खेल के मैदान डिजाइनर भी, इस भालू जाल के बारे में नहीं जानते। :) –

0

3 अन्य संभावित बड़े प्रदर्शन में सुधार करता है, तो आप एक पूरे, बड़ा सा फ़ाइल को पढ़ने और एक सरणी में यह टुकड़ा करने की क्रिया:

  1. sysread साथ बफ़र हो बंद करें (पढ़ने के बजाय)() (मैनुअल के बारे में ने चेतावनी दी है मिश्रण)
  2. पूर्व का विस्तार पिछले तत्व मूल्य द्वारा सरणी - स्मृति आवंटन की बचत होती है
  3. उपयोग अनपैक() uint16_t ग्राफिक्स चैनल डेटा की तरह तेजी से विभाजन के आंकड़ों के

फ़ंक्शन में एक सरणी को रेफरी करने से मुख्य प्रोग्राम एक साधारण सरणी से निपटने की अनुमति देता है जबकि लिखने-एक-भूल-भूल कार्यकर्ता फ़ंक्शन अधिक जटिल "$ @" और तीर -> [$ II] पहुंच का उपयोग करता है रूपों। काफी सीश होने के नाते, यह तेजी से होने की संभावना है!

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