2011-05-03 23 views
5

में एक अदिश संदर्भ पासिंग मुझे पता है कि एक उप करने के लिए एक अदिश गुजर वास्तव में संदर्भ गुजर रहा है, लेकिन जब से मैं मैं अभी भी निम्न परीक्षण किया पर्ल के लिए नया हूँ:पर्ल

#!/usr/bin/perl 
$i = 2; 
subr(\$i); 
sub subr{ 
    print $_[0]."\n"; 
    print $$_[0]."\n"; 
} 

मैं पहली पंक्ति में सोचा एक पता मुद्रित करने जा रहा है और दूसरी पंक्ति देने के लिए जा रहा है, लेकिन दूसरा एक खाली रेखा है। मुझे ऐसा करने के लिए किसी और ने इंगित किया था: ${$_[0]} और यह संख्या प्रिंट करता है। लेकिन उसे कारण नहीं पता था कि क्यों {} यह काम नहीं कर रहा है और यह {} के साथ क्यों काम कर रहा है। तो क्या हुआ है?

उत्तर

13

यह जब क्या आप चाहते हैं

my $x = $_[0]; print $$x; 

दूसरे शब्दों में है, क्योंकि अपने दूसरे प्रिंट बयान ऐसा करने के बराबर है

my $x = $$_; print $x[0]; 

है ..., de-संदर्भित सरणी सबस्क्रिप्ट से पहले होता है मूल्यांकन किया जाता है।

जब आप उन कर्ल-वुर्ली जोड़ते हैं, तो यह अभिव्यक्ति को समझने के लिए बताता है कि अभिव्यक्ति की व्याख्या कैसे करें; यह पहले $_[0] का मूल्यांकन करेगा, और फिर मूल्य प्राप्त करने के लिए डी-रेफरेंस करेगा।

+0

यह बहुत अच्छा है, धन्यवाद – user685275

7

यह ऑर्डर-ऑफ-मूल्यांकन चीज है।

$$_[0] is evaluated as {$$_}[0] 

यह स्केलर परिवर्तनीय $ _ के संदर्भ का 0 वां तत्व है। यह पहले संदर्भ ले रहा है और फिर इसके 0 वें तत्व को खोजने का प्रयास कर रहा है।

${$_[0]} 

यह सरणी @_ के 0 वें तत्व का संदर्भ है। यह पहले 0 वें तत्व को ढूंढ रहा है और उसके बाद इसका संदर्भ ले रहा है।

यदि आप अपने कोड के शीर्ष पर use strict और use warnings सेट करते हैं तो आपको अपने पहले प्रयास से अपरिभाषित मानों के बारे में बहुत सारी चेतावनियां दिखाई देगी।

+0

यह बहुत अच्छा है, धन्यवाद – user685275

1

आपको $i का संदर्भ पास करने की आवश्यकता नहीं है। जब आप इसे subr($i) के रूप में आमंत्रित करते हैं तो $_[0]उर्फ ​​$i के लिए नोटेशन है।

use strict; 
use warnings; 
use Test::More tests => 2; 

sub subr{ $_[0]++ } # messing with exactly what was passed first 
my $i=2; 
is($i, 2, q[$i == 2]); 
subr($i); 
is($i, 3, q[$i == 3]); 

एक और उदाहरण यह है:

use strict; 
use warnings; 
use Test::More tests => 6; 
use Test::Exception; 

sub subr{ $_[0]++ } 
my $i=2; 
is($i, 2, q[$i == 2]); 
subr($i); 
is($i, 3, q[$i == 3]); 

sub subr2 { $_[0] .= 'x'; } 
dies_ok { subr2('lit'); } 'subr2 *dies* trying to modify a literal'; 
lives_ok { 
    my $s = 'lit'; 
    subr2($s); 
    is($s, 'litx', q[$s eq 'litx']); 
    subr2((my $s2 = 'lit')); 
    is($s2, 'litx', q[$s2 eq 'litx']); 
} 'subr2 lives with heap variables'; 

आउटपुट:

ok 1 - $i == 2 
ok 2 - $i == 3 
ok 3 - subr2 *dies* trying to modify a literal 
ok 4 - $s eq 'litx' 
ok 5 - $s2 eq 'litx' 
ok 6 - subr2 lives with heap variables 
1..6 
3

$$_[0] केवल सरणी नाम के स्थान पर $ _ के साथ, $foo[0] की तरह है। इसका मतलब है कि $ _ को सरणी संदर्भ के रूप में माना जाता है, और अभिव्यक्ति में स्केलर संदर्भ $_[0] बिल्कुल शामिल नहीं है। $_->[0] वैकल्पिक -> सिंटैक्स का उपयोग कर समतुल्य है। Dereferencing के लिए सिंटेक्स मनमाने ढंग से और याद रखने के लिए मुश्किल लग सकता है, लेकिन अंतर्निहित भावना और व्यवस्था है; इसकी एक बहुत अच्छी प्रस्तुति http://perlmonks.org/?node=References+quick+reference पर है।