六、子程序的引用 perl中子程序的引用與C中函數的指針類似,構造方法如下: $pointer_to_sub = sub {... declaration of sub ...}; 通過所構造的引用調用子程序的方法為: &$pointer_to_sub(parameters);
·子程序模板 子程序的返回值不僅限于數據,還可以返回子程序的引用。返回的子程序在調用處執行,但卻是在最初被創建的調用處被設置,這是由Perl對Closure處理的方式決定的。Closure意即如果你定義了一個函數,它就以最初定義的內容運行。(Closure詳見OOP的參考書)下面的例子中,設置了多個錯誤信息顯示子程序,這樣的子程序定義方法可用于創建模板。
#!/usr/bin/perl sub errorMsg { my $lvl = shift; # # define the subroutine to run when called. # return sub { my $msg = shift; # Define the error type now. print "Err Level $lvl:$msg\n"; }; # print later. } $severe = errorMsg("Severe"); $fatal = errorMsg("Fatal"); $annoy = errorMsg("Annoying");
&$severe("Divide by zero"); &$fatal("Did you forget to use a semi-colon?"); &$annoy("Uninitialized variable in use"); 結果輸出如下:
Err Level Severe:Divide by zero Err Level Fatal:Did you forget to use a semi-colon? Err Level Annoying:Uninitialized variable in use 上例中,子程序errorMsg使用了局域變量$lvl,用于返回給調用者。當errorMsg被調用時,$lvl的值設置到返回的子程序內容中,雖然是用的my函數。三次調用設置了三個不同的$lvl變量值。當errorMsg返回時,$lvl的值保存到每次被聲明時所產生的子程序代碼中。最后三句對產生的子程序引用進行調用時$msg的值被替換,但$lvl的值仍是相應子程序代碼創建時的值。 很混淆是嗎?是的,所以這樣的代碼在Perl程序中很少見。 七、數組與子程序 數組利于管理相關數據,本節討論如何向子程序傳遞多個數組。前面我們講過用@_傳遞子程序的參數,但是@_是一個單維數組,不管你傳遞的參數是多少個數組,都按序存貯在@_中,故用形如my(@a,@b)=@_; 的語句來獲取參數值時,全部值都賦給了@a,而@b為空。那么怎么把一個以上的數組傳遞給子程序呢?方法是用引用。見下例:
#!/usr/bin/perl @names = (mickey, goofy, daffy ); @phones = (5551234, 5554321, 666 ); $i = 0; sub listem { my ($a,$b) = @_; foreach (@$a) { print "a[$i] = " . @$a[$i] . " " . "\tb[$i] = " . @$b[$i] ."\n"; $i++; } } &listem(\@names, \@phones); 結果輸出如下:
a[0] = mickey b[0] = 5551234 a[1] = goofy b[1] = 5554321 a[2] = daffy b[2] = 666
注意: 1、當想傳遞給子程序的參數是多于一個的數組時一定要使用引用。 2、一定不要在子程序中使用形如 (@variable)=@_; 的語句處理參數,除非你想把所有參數集中到一個長的數組中。 八、文件句柄的引用 有時,必須將同一信息輸出到不同的文件,例如,某程序可能在一個實例中輸出到屏幕,另一個輸出到打印機,再一個輸出到記錄文件,甚至同時輸出到這三個文件。相比較于每種處理寫一個單獨的語句,可以有更好的實現方式如下: spitOut(\*STDIN); spitOut(\*LPHANDLE); spitOut(\*LOGHANDLE); 其中子程序spitOut的代碼如下:
sub spitOut { my $fh = shift; print $fh "Gee Wilbur, I like this lettuce\n"; } 注意其中文件句柄引用的語法為\*FILEHANDLE。
|