Learning Perl 8

符號引用

    一般來說,類似$$var的結構表示,$var是一個引用變量,而且程序員希望該表達式能夠返回$var所指向的值。
假如$var不是引用變量的話會出現什麼情況呢?Perl並不是斷然打印出錯誤信息,而是嘗試檢查$var的值是否爲一字符串。如果是,Perl將以該字符串作爲正規的變量名與這個變量重新加以組合!考慮下面的例子:
#!/usr/bin/perl
$x=10;
$var="x";
$$var=30;
print $x."\n";
print $$var."\n";
print "$$var\n";
${$var}=25;
print "${$var}"."\n";
 
    當對$$var進行間接訪問時,Perl首先檢查$var是否是引用,在這裏它不是,而是字符串。於是Perl會再給該表達式一次機會:它將$var的內容當作變量標識符($x)。這樣一來,最終$x的值就被修改成30了。
    應當注意重要的一點是符號引用只對全局變量有效,而不能應用於那些用my標識爲私有的變量。
 
符號引用對數組和散列表同樣適用:
$var = "x";
@$var = (1,2,3); #將@x的值設置爲右邊的枚舉列表
     注意$var前面的符號指示變量的存取類型:$$var等價於$x,@$var也等價於@x,這種特性非常有用。
     對於那些在Perl的早期版本中就實現過此類功能的人來說,這要比使用eval更爲高效。舉例說明,你要在自己的腳本程序中,處理諸如“-Ddebug_level=3”的選項,並設置$debug_level變量。下面是其中的一種實現方式:
while($arg = shift @ARGV){
if($arg =~ /-D(\w+)=(\w+)/){
$var_name = $1; $value = $2;
$$var_name = $value; #更爲簡潔的可書寫爲:$$1 = $2;
}
}
     從另一方面說,Perl竭盡全力使一個表達式正常工作,有時卻於事無補。在前面的例子中,如果你所希望程序使用一個真正的引用,而不是字符串的話,那麼你就會希望Perl能夠指出這種情況而不是做任何的假定。幸運的的是,這種“急於求成”的方式可以被關閉。
     Perl有許多編譯時指令和指示。strict編譯指示將告訴Perl做嚴格的錯誤檢查。你甚至科以指定需要進行嚴格檢查的範圍,其中之一就包括“refs”這一項:
        use strict 'refs';    #告訴Perl不允許符號引用
        $var = "x";
        $$var = 30;
無論何時你試圖使用符號引用時均會導致運行時錯誤:
can't use string ("x") as a SCALAR ref while "strict refs" in use at try.pl line 3
strict指令直至程序塊結束仍然有效。可以通過輸入no strict 或更明確的no strict 'refs'將其關閉。
 
硬引用
1. 另一種數據類型的地址。硬引用本身是標量值。
$ptr=\任何其他類型:$,@,%,&,*(typeglob),$(another ptr)
引用本身是SCALAR保存的是指針值,引用的內容是$$ptr, %$ptr, @$ptr等等。
 
2. 創建對變量的引用(指針)時沒有必要命名,如果變量或者子程序沒有名稱則成爲匿名變量或匿名子程序。中綴運算符->用於分離匿名數字和匿名散列的引用(非必須,但是增加程序可讀性)。
匿名數字元素包含在放括號[]中,方括號表達式不同與下標表達式,用於給標量賦值的情況。注意“”中[]爲字面量。例如
my $arrayref = ['luffy', 'nami', 'robin'];
print $arrayref->[1].”\n”;
print $$arrayref[1].”\n”;
print ${$arrayref}[1].”\n”; #這三種形式相同
print “@{$arrayref}\n” #整個數組
#匿名哈希通過{}判斷,同樣這裏與散列下標的花括號不同,它用於將散列賦值給標量引用。
my $hashref = {Captain=”luffy”, Helmsman=”nami”, Historian=”robin”}
print “$hashref->{Captain}\n”;
print keys %$hashref, “\n”;
 對於各類嵌套數據結構的使用(等同於匿名數組/哈希)同樣可以使用$array->[3]->[3],${$array->[3]}[3], 或者$array->[3][3]; 而@{$array->[3]}表示整個嵌套數字,%{$array->[2]}表示真個嵌套哈希。內嵌套哈希的哈希可以用$hashref->{Captain}->{Luffy}或者直接$$hashref{Captain}{Luffy}。
#!/usr/bin/perl
 
my $hashref={Captain=>"luffy", Helmsman=>"nami", Historian=>"robin"};
my $arrayref = [1, 2, $hashref]; #注意這裏不能是%$hashref .
#print print $arrayref->[2]; #類型是HASH(地址);
print $arrayref->[2]->{Captain};
 
3. 匿名子程序
my $subref=sub{print @_;};
&$subref('a','b','c');
子程序傳遞引用:以往傳遞子程序時,都複製到@_數組中。如果變量太大會造成@_太大,需要放回的結果也太大。因此傳遞變量最有效和最簡單的方式就是通過地址引用(依然通過@_傳遞地址,和C差不多)。
sub gifts{
 my($n, $a) = @_; #將引用本地化
 print “There are $$n gifts”;
 print “@$t\n”;
 push(@$t, 'abcd');
}
gifts(\$num, \@toys); #然後abcd被實際插入到了@toys中。
 
4. 文件句柄引用
open(LOG, “/etc/passwd”) || die “error while opening”;
&readit(\*LOG)
sub readit{
my($mylog)=@_;
while(<$mylog>) {
print;
}
close $mylog; #這裏關閉,外面就不可以使用這個文件句柄了!
}
 
5. ref函數:用於測試引用存在,如果參數是引用則返回真。如果在printf “%s”還可以顯示引用的類型。
$ptr = \@arr;
printf(“\$ptr is a reference to %s”, ref($ptr)) if ref($ptr);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章