2013-10-18 56 views
7

請參閱下面的代碼情況下提領:

$scalar = 10; 

subroutine(\$scalar); 

sub subroutine { 
    my $subroutine_scalar = ${$_[0]}; #note you need the {} brackets, or this doesn't work! 
    print "$subroutine_scalar\n"; 
} 

在上面的代碼中,你可以看到寫的評論「的說明你需要{}括號,否則這不起作用!「 。請解釋一下,爲什麼我們不能使用相同的語句作爲理由:

my $subroutine_scalar = $$_[0]; 

即不使用大括號。

回答

2

${ $x }[0]獲取$x引用的數組中元素0的值。

${ $x[0] }獲取由數組@x的元素0引用的標量的值。

>perl -E"$x=['def']; @x=\'abc'; say ${ $x }[0];" 
def 

>perl -E"$x=['def']; @x=\'abc'; say ${ $x[0] };" 
abc 

$$x[0]${ $x }[0]的簡稱。

>perl -E"$x=['def']; @x=\'abc'; say $$x[0];" 
def 
1

因爲$$_[0]意味着${$_}[0]

考慮這兩個代碼其中兩個打印10件:

sub subroutine1 { 
    my $scalar = 10; 
    my $ref_scalar = \$scalar; 
    my @array = ($ref_scalar); 
    my $subroutine_scalar = ${$array[0]}; 

    print "$subroutine_scalar\n"; 
} 

sub subroutine2 { 
    my @array = (10); 
    my $ref_array = \@array; 
    my $subroutine_scalar = $$ref_array[0]; 

    print "$subroutine_scalar\n"; 
} 

subroutine1@array是含有的$scalar基準的陣列。因此,第一步是獲得$array[0]的第一個元素,然後遵循它。

儘管在subroutine2@array是含有標量10陣列,和$ ref_array是其參考。所以第一步是通過$ref_array獲取數組,然後索引數組。

2
my $subroutine_scalar = $$_[0]; 

是相同

my $subroutine_scalar = $_->[0]; # $_ is array reference 

在另一方面,對於@_數組的第一元素

my $subroutine_scalar = ${$_[0]}; 

解除引用的標量ref,將可寫爲

my ($sref) = @_; 
my $subroutine_scalar = ${$sref}; # or $$sref for short 
8

很多人都有準備在這裏得到正確答案。我想添加一個我發現照亮的例子。您可以閱讀perldoc perlref中的文檔以獲取更多信息。

您的問題是含糊之一,您有兩個操作$$[0]工作在相同的標識符_,並且結果取決於首先執行哪個操作。我們可以通過使用支持花括號${ ... }來減少歧義。 $$_[0]可以(反正人)可能意味着:

  • ${$$_}[0] - 取消引用標$_,然後取它的第一個元素。
  • ${$_[0]} - 取數組@_的元素0並將其解引用。

如您所見,這兩種情況指的是完全不同的變量,即@_$_

當然,Perl的它一點也不含糊,我們只是得到了第一個選項,因爲之前鍵查找,進行提領。我們需要支持大括號覆蓋此非關聯化,這就是爲什麼你的例子並不「工作」不支持括號。

你可能會考慮爲你的子程序一個稍微不那麼混亂的功能。不要試圖同時做兩件事情(獲取參數,並取消對它的引用),你可以做兩個階段:

sub foo { 
    my $n = shift; 
    print $$n; 
} 

在這裏,我們起飛@_第一個參數與shift,然後取消對它的引用。清潔和簡單。

大多數情況下,你將不會被使用標量變量的引用,但是。在這些情況下,您可以使用箭頭操作符->

my @array = (1,2,3); 
foo(\@array); 

sub foo { 
    my $aref = shift; 
    print $aref->[0]; 
} 

我發現使用箭頭操作符是最好的$$語法。