2009-04-29 10 views
32

मेरे पास एक ऐसा फ़ंक्शन है जो एक चर और एक सहयोगी सरणी लेता है, लेकिन मुझे लगता है कि वे सही पास नहीं कर पाएंगे। मुझे लगता है कि इसमें फ़ंक्शन घोषणाओं के साथ कुछ करना है, हालांकि मैं यह नहीं समझ सकता कि वे पर्ल में कैसे काम करते हैं। क्या इसके लिए कोई अच्छा संदर्भ है और मुझे जो चाहिए वह पूरा कैसे कर सकता हूं?मैं पर्ल में किसी फ़ंक्शन में हैश कैसे पास करूं?

मुझे यह जोड़ना चाहिए कि इसे संदर्भ द्वारा पारित करने की आवश्यकता है।

sub PrintAA 
{ 
    my $test = shift; 
    my %aa = shift; 
    print $test . "\n"; 
    foreach (keys %aa) 
    { 
     print $_ . " : " . $aa{$_} . "\n"; 
     $aa{$_} = $aa{$_} . "+"; 
    } 
} 
+0

क्या आप हमें कोड दिखा सकते हैं? –

+0

क्या आप हमें कॉलिंग कोड दिखा सकते हैं? –

उत्तर

60

हैश के बजाय संदर्भ पास करें।

PrintAA("abc", \%fooHash); 

sub PrintAA 
{ 
    my $test = shift; 
    my $aaRef = shift; 

    print $test, "\n"; 
    foreach (keys %{$aaRef}) 
    { 
    print $_, " : ", $aaRef->{$_}, "\n"; 
    } 
} 

में के रूप में भी देखें perlfaq7: How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}?

+0

हालांकि मुझे नहीं लगता कि इसे कैसे किया जाना चाहिए, यह सबसे आसान तरीका है। – rlbond

4

ऐसा लगता है कि आप एक हैश के लिए एक संदर्भ में पास करना चाहिए।

sub PrintAA 
{ 
    my $test = shift; 
    my $aa = shift; 
    if (ref($aa) != "HASH") { die "bad arg!" } 
    .... 
} 

PrintAA($foo, \%bar); 

कारण आप क्योंकि पर्ल एक सूची में एक सबरूटीन के लिए सभी तर्कों सपाट एक

my %aa = shift; 

है ऐसा नहीं कर सकते, @_। प्रत्येक तत्व की प्रतिलिपि बनाई जाती है, इसलिए संदर्भ में गुजरने से उन प्रतियों से बचा जाता है।

12
वैकल्पिक रूप से

:

sub PrintAA 
{ 
    my $test  = shift; 
    my %aa   = @_; 
     print $test . "\n"; 
     foreach (keys %aa) 
     { 
       print $_ . " : " . $aa{$_} . "\n"; 
       $aa{$_} = $aa{$_} . "+"; 
     } 
} 

बात आप मौलिक भूल रहे हैं कि एक साहचर्य सरणी एक भी तर्क (हालांकि एक साहचर्य सरणी संदर्भ है, पॉल Tomblin के जवाब के रूप में) है।

3

सामान्य रूप से कई तरीके हैं। यहां बताया गया है Perl Best Practices, कि ज्यादातर शैली संकेत के श्रद्धेय है, मानकों कार्यों के लिए पारित करने के बारे में कहना है: तीन से अधिक मापदंडों

लेकिन चूंकि किसी भी ऐसे सबरूटीन के लिए नामित किया तर्कों की एक हैश

उपयोग

my $scalar = 5; 
my %hash = (a => 1, b => 2, c => 3); 

func($scalar, %hash) 

और समारोह इस तरह परिभाषित किया गया है:

इस तरह से उन्हें सीधे गुजर के साथ); आप केवल दो है, तो आप दूर हो सकता है
sub func { 
    my $scalar_var = shift; 
    my %hash_var = @_; 

    ... Do something ... 
} 

यदि आप कुछ कोड दिखा सकते हैं तो यह अधिक उपयोगी हो सकता है।

15

इस कोड काम करता है:

#!/bin/perl -w 

use strict; 

sub PrintAA 
{ 
    my($test, %aa) = @_; 
    print $test . "\n"; 
    foreach (keys %aa) 
    { 
     print $_ . " : " . $aa{$_} . "\n"; 
    } 
} 

my(%hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA); 

PrintAA("test", %hash); 

प्रमुख मुद्दा मेरी() फंक्शन में 'बयान' में सरणी संदर्भ का उपयोग है।


क्या सरणी संदर्भ व्यवसाय वास्तव में क्या करता है?

संक्षेप में, यह सही तरीके से काम करता है।

इसका मतलब है कि @_ तर्कों में से पहला मान $test पर दिया गया है, और शेष आइटम हैश %aa को असाइन किया गया है। जिस तरह से मैंने इसे बुलाया, @_ में वस्तुओं की एक विषम संख्या है, इसलिए एक बार जब पहली आइटम $test पर असाइन की जाती है, तो %aa को असाइन करने के लिए कई आइटम उपलब्ध हैं, प्रत्येक जोड़ी के पहले आइटम के साथ कुंजी ('aaa', 'bbb', 'ccc' मेरे उदाहरण में), और दूसरा संबंधित मान है।

@aa के साथ प्रतिस्थापित करना संभव होगा, इस स्थिति में, सरणी में 6 आइटम होंगे। को $aa के साथ प्रतिस्थापित करना भी संभव होगा, और उस स्थिति में, चर $aa में 'aaa' मान होगा, और @_ में शेष मान असाइनमेंट द्वारा अनदेखा किए जाएंगे।

यदि आप परिवर्तनीय सूची के चारों ओर कोष्ठक छोड़ देते हैं, तो पर्ल कोड को संकलित करने से इंकार कर देता है। विकल्प जवाब में से एक अंकन से पता चला है:

my $test = shift; 
my(%aa) = @_; 

यह मैं क्या लिखा है के लिए काफी होता है; अंतर यह है कि दो my कथन के बाद, @_ में केवल इस भिन्नता में 6 तत्व हैं, जबकि एकल my संस्करण में, इसमें अभी भी 7 तत्व हैं।

सरणी संदर्भ के बारे में SO में निश्चित रूप से अन्य प्रश्न हैं।


वास्तव में, मैं my($test, %aa) = @_; मैं पूछ रहा था के बारे में my(%hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA);my %hash = { 'aaa' => 1, ... }; बनाम

अंतर यह है कि {...} अंकन एक हैश रेफरी और (उत्पन्न करता है के बारे में पूछ नहीं किया गया था ...) नोटेशन एक सूची उत्पन्न करता है, जो एक हैश के लिए नक्शा बनाता है (हैश रेफ के विपरीत)। इसी तरह, [...] एक सरणी रेफरी उत्पन्न करता है और एक सरणी नहीं।

वास्तव में, 'मुख्य' कोड बदलें ताकि यह पढ़ सके: मेरा (% हैश) = {...}; और आप एक रन-टाइम मिलता है (लेकिन समय संकलन) त्रुटि - सावधानी के साथ इलाज लाइन नंबर के बाद से मैं अपनी फ़ाइल के लिए वैकल्पिक codings जोड़ दिया है:

Reference found where even-sized list expected at xx.pl line 18. 
... 
Use of uninitialized value in concatenation (.) or string at xx.pl line 13. 
+2

TMTOWTDI, लेकिन मैं इस दृष्टिकोण को पसंद करता हूं। – spoulson

+0

सरणी संदर्भ व्यवसाय वास्तव में क्या करता है? –

+0

वास्तव में, मैं मेरे ($ परीक्षण,% aa) = @_ के बारे में नहीं पूछ रहा था; मैं मेरे (% हैश) = ('aaa' => 1, 'bbb' => 'गेंद', 'ccc' => \ & printAA) के बारे में पूछ रहा था; बनाम मेरा% हैश = {'aaa' => 1, ...}; –

3

उपरोक्त सभी तरीकों काम करते हैं, लेकिन यह हमेशा तरीका था मैं इस तरह की चीजों को करना पसंद करता हूं:

sub PrintAA ($\%) 
{ 
    my $test  = shift; 
    my %aa   = ${shift()}; 
    print "$test\n"; 
    foreach (keys %aa) 
    { 
     print "$_ : $aa{$_}\n"; 
     $aa{$_} = "$aa{$_}+"; 
    } 
} 

नोट: मैंने आपका कोड थोड़ा सा भी बदल दिया। पर्ल की डबल-उद्धृत तार "$test" की वास्तविक स्ट्रिंग '$test' की बजाय $test का मान होने के लिए व्याख्या करेंगे, इसलिए आपको . s की आवश्यकता नहीं है।

इसके अलावा, मैं प्रोटोटाइप कैसे काम करता हूं इसके बारे में गलत था।एक हैश पास करने के लिए, इस का उपयोग करें:

PrintAA("test", %hash); 

एक हैश संदर्भ मुद्रित करने के लिए इस का उपयोग करें:

PrintAA("test", %$ref_to_hash); 
बेशक

, अब आप क्योंकि आप भेज रहे हैं हैश $ref_to_hash द्वारा संदर्भित संशोधित नहीं कर सकते एक प्रतिलिपि, लेकिन आप कच्चे %hash को संशोधित कर सकते हैं क्योंकि आप इसे संदर्भ के रूप में पास कर रहे हैं।

+0

डाउनवॉटेड क्योंकि 1) यह कोड काम नहीं करता है और 2) पर्ल प्रोटोटाइप ऐसा नहीं करते हैं जो ज्यादातर लोग (स्पष्ट रूप से आप सहित) उन्हें उम्मीद करते हैं। वे अंतर्निहित कार्यों के व्यवहार को अनुकरण करने के लिए अच्छे हैं लेकिन अन्यथा अधिक उपयोग नहीं करते हैं। प्रोटोटाइप का "\%" हिस्सा कहता है कि दूसरा तर्क एक हैश होना चाहिए और इसे संदर्भ से पास करना होगा। यह एक * असली * हैश होना चाहिए। यह हैशफ या कुंजी => वैल्यू जोड़े की सूची नहीं हो सकती है। –

+0

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

0

उपयोग folowing उप हैश या hashref पाने के लिए - जो कुछ भी पारित कर दिया :)

sub get_args { ref($_[0]) ? shift() : (@_ % 2) ? {} : {@_}; } 
sub PrintAA 
{ 
    my $test = shift; 
    my $aa = get_args(@_);; 
    #then 
    $aa->{somearg} #do something 
    $aa->{anotherearg} #do something 

} 

इस तरह अपने कार्य कॉल करें:

printAA($firstarg,somearg=>1, anotherarg=>2) 

या इस तरह (कोई बात नहीं):

printAA($firstarg,{somearg=>1, anotherarg=>2}) 

या यहां तक ​​कि इस (कोई बात नहीं) की तरह:

my(%hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA); 

PrintAA("test", %hash); 

चीयर्स!

+0

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

+0

यह हैश (रेफरी) के लिए है :) - मुझे पता है कि यह arrays –

+0

@Chris के साथ काम नहीं करता है - प्रोटोटाइप का कोई प्रभाव नहीं पड़ता है जब एक सबराउटिन विधि के रूप में बुलाया जाता है, वे भयानक और भ्रमित और चीजों को तोड़ते हैं। जैसा कि पहले किसी और ने पोस्ट किया था, तब तक उनका उपयोग न करें जब तक कि आपको अंतर्निहित उप-कार्य करने की आवश्यकता न हो। – converter42

1

कार्यों के लिए तर्क एक सारिणी (@_) में चपटा मिलता है। तो संदर्भ के अनुसार हैश को पास करना आमतौर पर आसान होता है।

my %myhash = (key1 => "val1", key2 => "val2"); 

कि HASH के लिए एक संदर्भ बनाने के लिए::

एक हैश बनाने के लिए

my $href = \%myhash 

संदर्भ द्वारा कि हैश का उपयोग करने के लिए;

%$href 

तो अपने उप में:

my $myhref = shift; 

keys %$myhref; 
1

अन्य सभी यहाँ प्राप्त उत्तरों अब तक नहीं बल्कि मेरे लिए जटिल लगते हैं। जब मैं पर्ल फ़ंक्शन लिखता हूं तो मैं आमतौर पर फ़ंक्शन की पहली पंक्ति में सभी उत्तीर्ण तर्कों का विस्तार "विस्तार" करता हूं।

sub someFunction { 
    my ($arg1, $arg2, $arg3) = @_; 

यह अन्य भाषाओं, जहाँ आप के रूप में

... someFunction (arg1, arg2, arg3) 

कार्यों की घोषणा और यदि आप इसे इस तरह से करते हैं और अंतिम तर्क के रूप में हैश गुजरती हैं, तो आप किसी भी चाल के बिना ठीक हो जाओगे के समान है या विशेष जादू। उदाहरण के लिए:

sub testFunc { 
    my ($string, %hash) = @_; 
    print "$string $hash{'abc'} $hash{'efg'} $string\n"; 
} 

my %testHash = (
    'abc' => "Hello", 
    'efg' => "World" 
); 
testFunc('!!!', %testHash); 

उत्पादन की उम्मीद के रूप में किया जाता है:

!!! Hello World !!! 

यह काम करता है पर्ल बहस में becaus हमेशा अदिश मूल्यों की एक सरणी के रूप में पारित कर रहे हैं और अगर आप एक हैश गुजरती हैं, यह महत्वपूर्ण मूल्य है/जोड़े हैं उस सरणी में जोड़ा गया। ऊपर नमूने में, तर्क सरणी (@_) के रूप में कार्य करने के लिए पारित कर दिया वास्तव में कर रहे हैं:

'!!!', 'abc', 'Hello', 'efg', 'World' 

और '!!!'%string को सरल असाइन किया गया है, जबकि %hash अन्य सभी तर्कों को "निगलता है", हमेशा एक कुंजी के रूप में व्याख्या करता है और अगले के रूप में मूल्य (जब तक सभी तत्वों का उपयोग नहीं किया जाता है)।

आप इस तरह से कई हैंश पास नहीं कर सकते हैं और हैश पहला तर्क नहीं हो सकता है, अन्यथा यह सबकुछ निगल जाएगा और अन्य सभी तर्कों को बिना असाइन किए जाएंगे।

बेशक बिल्कुल अंतिम तर्क के रूप में सरणी के लिए एक ही काम करता है। यहां केवल अंतर यह है कि सरणी कुंजी और मानों के बीच अंतर नहीं करती है, उनके लिए छोड़कर सभी तर्क मूल्य हैं और केवल सरणी पर धक्का देते हैं।