मैं dereferencing के साथ समस्याओं में भागता रहता हूं, खासकर जब फ़ंक्शन से मान लौटाता हूं।

मुद्दा यह प्रतीत होता है कि जब भी आप किसी स्केलर के अलावा कुछ भी वापस करते हैं तो आप वास्तव में उस वस्तु को संदर्भ द्वारा वापस कर रहे हैं - जो मेरे द्वारा ठीक है - लेकिन कहें कि जब हम इन संदर्भों को अन्य कार्यों में पास करते हैं और हमें फिर से उनकी हिम्मत तक पहुंच की आवश्यकता होती है तो हम कैसे करते हैं सही ढंग से करो?

मैं त्रुटियों में भागता रहता हूं जैसे: "परमों की संख्या की भी अपेक्षा करना संदर्भ मिला" या प्रभाव के लिए कुछ।

क्या कोई सामान्य नियम है जिसका उपयोग मैं इस पूरी प्रक्रिया को सरल बनाने के लिए कर सकता हूं? मैं लगभग चाहता हूं कि मुझे dereferencing के बारे में चिंता न करनी पड़े!

यहां कुछ ऐसा उदाहरण दिया गया है जिसे मैंने आज पहले करने की कोशिश की, और सभी प्रकार की डेरेफेरेंसिंग समस्याओं में भाग गया, जिसे मैंने अपने रास्ते को खराब करने की कोशिश में कुछ घंटे बिताए - इसलिए पढ़ने, कोशिश करने और असफल होने के बाद, मैं यहां आपसे पूछने के लिए हूं मंदी के लिए।

व्यक्ति आपत्ति

Person
 has name [Str]
 has madeby [Str]
 has height [Num]
 has id [Num]

किसी व्यक्ति को वस्तु बनाने के विभिन्न तरीके

sub person_maker{
 my($this,%options) = @_;
 my $person = Person->new(%options);
   return $person;
}

sub make_person_named_james{
 my($this,$options) = @_;
 my $default = { name => 'James', madeby => 'name' };
   $options = ($options,$defaults); #merge default and options hash
   return($this->person_maker($options));
}

sub make_person_from_id{
 my($this,$id) = @_;
 my $default = { name => 'nameless person', madeby => 'id' };
   $default = ($default,{ id => $id });
   return($this->person_maker($default);
}

sub make_person_from_person{
 my($this,$person) = @_;
 my $person_options = {
   name => $person->name().'_twin',
   height => $person->height(),
   id => $person->id() + 1,
   madeby => 'person'
 };
 return($this->person_make($person_options));
}
  • Func हैश ऑब्जेक्ट देता है => यह वास्तव में हैश . के रूप में वापस आता है संदर्भ
  • Func हैश संदर्भ => देता है, यह वास्तव में a . के रूप में वापस आता है स्केलर
  • Func सरणी ऑब्जेक्ट देता है => यह वास्तव में एक सरणी देता है संदर्भ
  • Func सरणी संदर्भ => देता है यह वास्तव में एक स्केलर . देता है ?
  • Func एक स्केलर => देता है, यह वास्तव में का मान लौटाता है अदिश?

अगर मुझे इनमें से कुछ भी गलत लगे तो मुझे सुधारें।

फिर मेरे लिए एक और मुद्दा एक समारोह के तर्कों का उपभोग करने के बिंदु पर है ..

मैं जो वापस लौटाता हूं उसके आधार पर ये बुरे लड़के अलग-अलग व्यवहार करने जा रहे हैं!

    sub myfunc{
      my($self,$args) = @_ # list of arguments (what if the args are mixed?)
  OR
      my($self,$args) = $_ # scalar (this wont work here $args will by undef
  OR
      my $self = shift; # pop the first arg
      my $args = shift; # pop the second arg
  OR
      my $self = $_[0] 
      my $args = $_[1]

इसके अलावा! वहाँ बहुत सारे दस्तावेज़ हैं, उनमें से कई पुराने हैं, इसलिए यह पता लगाना कठिन है कि इन स्थितियों में क्या करना सही या सबसे अच्छा है।

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

2
qodeninja 13 अक्टूबर 2011, 05:40

2 जवाब

सबसे बढ़िया उत्तर

सभी संदर्भ अदिश मान हैं

किसी संदर्भ को डी-रेफ़रेंस करने के लिए आवश्यक है कि आप संदर्भ के प्रकार को जानते हों। संदर्भ का प्रकार ref फ़ंक्शन का उपयोग करके पाया जा सकता है।

my $array_ref = [];
print ref $array_ref;  # prints: ARRAY

अलग-अलग प्रकारों को संदर्भित करना

  • स्केलर संदर्भ: $$scalar_ref

  • सरणी संदर्भ: @$array_ref

  • हैश संदर्भ: %$hash_ref

@_

@_ में पैरामीटर के उपनाम शामिल हैं। @_ को संशोधित करने से मूल मानों में संशोधन होता है। हमेशा जितनी जल्दी हो सके मापदंडों की एक प्रति बनाएं और उन प्रतियों पर काम करें; जिसे आप मूल मूल्यों को बदले बिना सुरक्षित रूप से संशोधित कर सकते हैं।

तर्क और वापसी मूल्य

पर्ल में, सभी फ़ंक्शन कॉल तर्क एक सूची में चपटे (ढह गए) होते हैं (इस प्रकार उनकी पहचान खो देते हैं) और इसलिए वापसी मान भी होते हैं। किसी फ़ंक्शन के दृष्टिकोण से, यह केवल और एकल मानों की सूची को स्वीकार करने में सक्षम है और मानों की केवल एकल सूची लौटा सकता है।

उदाहरण परिदृश्य:

किसी फ़ंक्शन के लिए स्केलर तर्क:

sub foo {
    my $arg = shift;
}

वही सभी संदर्भों पर लागू होता है; संदर्भ अदिश मान हैं।

किसी फ़ंक्शन के लिए ऐरे तर्क:

sub foo {
    my @args = @_;
}

foo( 'bar', 'baz' );
foo( ( 'bar', 'baz' ), ( 'qux', 'spam' ) );  # In no way can the foo subroutine identify that the original arguments were two lists (same with arrays).

किसी फ़ंक्शन के लिए हैश तर्क:

sub foo {
    my %arg = @_;
}

foo( 'bar' => 'baz' );
foo( ( 'bar' => 'baz' ), ( 'qux' => 'spam' ) );  # In no way can the foo subroutine identify that the original arguments were two hashes.

हमेशा संदर्भ पास करें जब एकाधिक सूचियां (सरणी) या हैश शामिल हों। इस तरह, आप अलग-अलग सूचियों की पहचान कर सकते हैं।

$_ और @_ भिन्न हैं

अपना कोड उद्धृत करना (जो $_ का गलत उपयोग करता है):

my($self,$args) = $_ # scalar (this wont work here $args will by undef

$_ को डिफ़ॉल्ट चर कहा जाता है और इसका उपयोग कई स्थितियों में किया जाता है जहां कोई स्पष्ट चर नहीं बताया गया है। दूसरी ओर @_ का उपयोग केवल फ़ंक्शन के अंदर सरणी पैरामीटर (उपनाम) रखने के लिए किया जाता है। प्रत्येक तत्व को संदर्भित करने के लिए, हम उपयोग कर सकते हैं: $_[0], $_[1], वगैरह।

संदर्भ

  • आप perldoc perlvar से पर्ल में पूर्वनिर्धारित चरों के बारे में अधिक पढ़ सकते हैं। मैं हमेशा अपने टर्मिनल से perldoc -v '$special_variable' का उपयोग करता हूं। यदि आप विंडोज का उपयोग करते हैं, तो सिंगल कोट्स को डबल कोट्स से बदलना होगा: perldoc -v "$special_variable"

  • पर्ल सबरूटीन्स: perldoc perlsub

  • पर्ल संदर्भ और नेस्टेड डेटा संरचनाएं: perldoc perlref

10
Alan Haggai Alavi 13 अक्टूबर 2011, 07:03
मैंने स्वीकृत उत्तर को अस्वीकार कर दिया क्योंकि यह सीधे पूछे जाने वाले प्रश्न का उत्तर नहीं देता है। ओपी किसी फ़ंक्शन के रिटर्न वैल्यू को हटाना चाहता है। हालाँकि, स्वीकृत उत्तर फ़ंक्शन तर्कों की बात करता है। वापसी मूल्य के बिल्कुल विपरीत! हो सकता है, प्रतिक्रिया के निचले भाग में आपको इस प्रश्न का उत्तर मिल जाए, लेकिन यह उत्तर निश्चित रूप से ट्रैक पर नहीं है। ओपी स्पष्ट रूप से जानता है कि संदर्भ क्या है, और उनका उपयोग कैसे करें। लेकिन यहां तक ​​कि, वर्षों के बाद भी, मुझे अभी भी "my @rv = @$functionName_asRef($param1, $param2)" का कोई रास्ता नहीं मिला है;
 – 
Jarett Lloyd
27 अक्टूबर 2018, 07:19

आप संदर्भों के साथ काम करने के कुछ महत्वपूर्ण पहलुओं को याद कर रहे हैं।

बुनियादी बातों से शुरू होकर, पर्ल में एक पहचानकर्ता यूनिकोड की जटिलताओं को छोड़कर [a-zA-Z_]\w+ से मेल खाने वाला एक स्ट्रिंग है। यह पहचानकर्ता नंगे हो सकता है, या एक सतर्क के साथ उपसर्ग कर सकता है।

ग्लोब, * सबसे महत्वपूर्ण और अक्सर अनदेखी की जाने वाली निगरानी है, जो सभी चीजों का कंटेनर है (कम से कम जब तक my को पार्टी को बर्बाद करना पड़ता है और अलग होना पड़ता है, एक पैड में छिपा होता है)।

जब आपके पास foo नाम का एक पहचानकर्ता होता है, तो *foo ग्लोब में वह सब होता है जो foo हो सकता है:

$foo as a scalar, a singular value
@foo as an array, a plural value
%foo as a hash, a plural value
&foo as code, singular if a reference \&foo, could be plural if making a call

अन्य प्रकार भी हैं, लेकिन वे कम आम हैं।

ऊपर दिए गए प्रत्येक उदाहरण में, सिगिल को पहचानकर्ता के सामने रखा जाता है, और ग्लोब *foo में संग्रहीत संदर्भ मानों को निष्क्रिय कर देता है। इसका पूरा सिंटैक्स थोड़ा बोझिल है @{*foo{ARRAY}}, इसलिए पर्ल आपको उदास अनदेखी ग्लोब सिगिल को छोड़ देता है और दूसरों का सीधे उपयोग करता है। हालांकि, आप कोष्ठकों को ${foo} या @{foo} या कोई अन्य सतर्क रख सकते हैं, जिसका अर्थ क्रमशः $foo और @foo जैसा ही है।

यह पता चला है कि आपको सिगिल के पीछे या ब्रैकेट के अंदर एक बेयरवर्ड पहचानकर्ता नहीं रखना है, लेकिन कोई एकवचन मूल्य है।

my $scalar_foo_ref = \$foo;

say $$scalar_foo_ref;   # prints $foo
say ${$scalar_foo_ref}; # same

सतर्क हमेशा अपने प्रकार (या एक जो होने का दिखावा कर सकता है) के मूल्य को कम करने की अपेक्षा करता है, और अन्यथा एक त्रुटि फेंक देगा।

तो निम्नलिखित कोड मानते हुए:

my @array = qw(a b c);

say $array[0];  # a
say join ', ' => @array;  # a, b, c

आप इसे आसानी से संदर्भों का उपयोग करने के लिए बदल सकते हैं। सबसे पहले आप संदर्भों का उपयोग करने के लिए घोषणा को बदल देंगे, जो स्केलर हैं, इसलिए $foo में संग्रहीत हैं:

my $array = [qw(a b c)]; # square brackets make an array ref
# or
my $array = \@array_of_hopefully_another_name; # \ does too

और फिर शेष कोड में, स्ट्रिंग array को संदर्भ के नाम से प्रतिस्थापित करें, $array:

say $$array[0];  # a
say join ', ' => @$array;  # a, b, c

बस इतना ही, संदर्भ के लिए सब कुछ है। तो, अंत में आपके कोड के लिए। निम्नलिखित पंक्तियाँ लें:

my $default = { name => 'James', madeby => 'name' };
$options = ($options,$defaults); #merge default and options hash

पहले में, आप एक अनाम हैश संदर्भ बनाने के लिए {...} निर्माण का ठीक से उपयोग करते हैं। आप इसे भयानक वर्बोज़ रूप में भी लिख सकते थे:

my $default = do {my %hash = (name => 'James', madeby => 'name'); \%hash};

लेकिन ऐसा मत करो।

अगली पंक्ति वह है जहाँ समस्याएँ होती हैं, और जहाँ आपको ऊपर से प्रतिस्थापन नियमों का पालन करने की आवश्यकता होती है। आपने शायद ऐसा कोड देखा है जो इस तरह दिखता है:

%options = (%options, %defaults);

और जब आपने सिगिल बदला, तो सब कुछ गलत हो गया। जब यह देखता है तो वास्तव में क्या पर्ल करता है:

$options = ($options, $defaults);

क्या यह निष्पादित होता है और फिर सूची के अंतिम तत्व को छोड़कर सब कुछ फेंक देता है (इस मामले में ($options, और फिर अंतिम तत्व को स्केलर को = के एलएचएस पर असाइन करता है, जिससे आपकी लाइन इसके बराबर हो जाती है:

$options = $defaults;

बेशक आप जो चाहते थे वह नहीं है। इसके बजाय, अपने हैशरेफ़ नामों को बेयरवर्ड नामों के लिए स्थानापन्न करें:

%$options = (%$options, %$defaults);

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

%$options = (%$defaults, %$options);

इन परिवर्तनों को अपने कोड में लागू करें जहाँ आप संदर्भों का उपयोग कर रहे हैं। चीजें फिर से समझ में आने लगेंगी।

4
Eric Strom 13 अक्टूबर 2011, 07:36