Perl 子程式也就是使用者定義的函數。
Perl 子程式即執行一個特殊任務的一段分離的程式碼,它可以使減少重複程式碼且使程式易讀。
Perl 子程式可以出現在程式的任何地方,語法格式如下:
sub subroutine{ statements;}
呼叫子程序語法格式:
subroutine( 參數列表);
在Perl 5.0 以下版本呼叫子程序方法如下:
&subroutine( 參數列表);
在新版本上,雖然也支援該呼叫方法,但不建議使用。
接下來我們來看一個簡單是實例:
實例
#!/usr/bin/perl # 函數定義sub Hello { print " Hello, World! n " ; } # 函數調用Hello ( ) ;執行以上程序,輸出結果為:
Hello, World!
向子程序傳遞參數
Perl 子程式可以和其他程式設計一樣接受多個參數,子程式參數使用特殊陣列@_ 來標示。
因此子程序第一個參數為$_[0], 第二個參數為$_[1], 以此類推。
不論參數是標量型還是陣列型的,使用者把參數傳給子程式時,perl預設會以引用的方式呼叫它們。
實例
#!/usr/bin/perl # 定義求平均值函數sub Average { # 取得所有傳入的參數 $n = scalar ( @_ ) ; $sum = 0 ; foreach $item ( @_ ) { $sum += $item ; } $average = $sum / $n; print '傳入的參數為: ',"@_n"; # 列印整個陣列 print "第一個參數值為: $_[0]n"; # 列印第一個參數print "傳入參數的平均值為: $averagen"; # 列印平均值} # 呼叫函數Average(10, 20, 30);執行以上程序,輸出結果為:
傳入的參數為: 10 20 30第一個參數值為: 10傳入參數的平均值為: 20
使用者可以透過改變@_ 數組中的值來改變對應實際參數的值。
向子程序傳遞列表
由於@_ 變數是數組,所以它可以向子程序中傳遞列表。
但如果我們需要傳入標量和陣列參數時,我們需要把列表放在最後一個參數上,如下所示:
實例
#!/usr/bin/perl # 定義函數sub PrintList { my @list = @_ ; print "列表為: @list n " ; } $a = 10 ; @b = ( 1 , 2 , 3 , 4 ) ; # 列表參數PrintList ( $a , @b ) ;以上程序將標量和數組合併了,輸出結果為:
列表為: 10 1 2 3 4
我們可以向子程序傳入多個數組和哈希,但是在傳入多個數組和哈希時,會導致丟失獨立的標識。所以我們需要使用引用(下一章節會介紹)來傳遞。
向子程序傳遞哈希
當向子程序傳遞哈希表時,它將複製到@_ 中,哈希表將展開為鍵/值組合的列表。
實例
#!/usr/bin/perl # 方法定義sub PrintHash { my ( %hash ) = @_ ; foreach my $key ( keys %hash ) { my $value = $hash { $key } ; print " $key : $value n " ; } } %hash = ( ' name ' => ' codercto ' , ' age ' => 3 ) ; # 傳遞哈希PrintHash ( %hash ) ;以上程式執行輸出結果為:
age : 3name : codercto
子程序回傳值
子程式可以向其他程式語言一樣使用return 語句來傳回函數值。
如果沒有使用return 語句,則子程式的最後一行語句將作為傳回值。
實例
#!/usr/bin/perl # 方法定義sub add_a_b { # 不使用return $_ [ 0 ] + $_ [ 1 ] ; # 使用return # return $_[0]+$_[1]; } print add_a_b ( 1 , 2 )以上程式執行輸出結果為:
3
子程序中我們可以傳回標量,數組和哈希,但是在傳回多個數組和哈希時,會導致丟失獨立的標識。所以我們需要使用引用(下一章節會介紹)來傳回多個陣列和函數。
子程式的私有變數
預設情況下,Perl 中所有的變數都是全域變量,這就是說變數在程式的任何地方都可以呼叫。
如果我們需要設定私有變量,可以使用my操作符來設定。
my運算子用於建立詞法作用域變量,透過my建立的變量,存活於聲明開始的地方,直到閉合作用域的結尾。
閉合作用域指的可以是一對花括號中的區域,可以是一個文件,也可以是一個if, while, for, foreach, eval字串。
以下實例示範如何宣告一個或多個私有變數:
sub somefunc { my $variable; # $variable 在方法somefunc() 外不可見my ($another, @an_array, %a_hash); # 同時宣告多個變數}
實例
#!/usr/bin/perl # 全域變數$string = " Hello, World! " ; # 函數定義sub PrintHello { # PrintHello 函數的私有變數 my $string ; $string = " Hello, Codercto! " ; print "函數內字串: $string n " ; } # 呼叫函數PrintHello ( ) ; print "函數外字串: $string n " ;以上程式執行輸出結果為:
函數內字串:Hello, Codercto!函數外字串:Hello, World!
變數的臨時賦值
我們可以使用local 為全域變數提供暫時的值,在退出作用域後將原來的值還回去。
local 定義的變數不存在於主程式中,但存在於該子程式和該子程式呼叫的子程式中。定義時可以賦予其賦值,如:
實例
#!/usr/bin/perl # 全域變數$string = " Hello, World! " ; sub PrintCodercto { # PrintHello 函數私有變數 local $string ; $string = " Hello, Codercto! " ; # 子程序呼叫的子程序 PrintMe ( ) ; print " PrintCodercto 函數內字串值: $string n " ; } sub PrintMe { print " PrintMe 函數內字串值: $string n " ; } sub PrintHello { print " PrintHello 函數內字串值: $string n " ; } # 函數調用PrintCodercto ( ) ; PrintHello ( ) ; print "函數外部字串值: $string n " ;以上程式執行輸出結果為:
PrintMe 函數內字串值:Hello, Codercto!PrintCodercto 函數內字串值:Hello, Codercto!PrintHello 函數內字串值:Hello, World!函數外部字串值:Hello, World!
靜態變數
state操作符功能類似C裡面的static修飾符,state關鍵字將局部變數變得持久。
state也是詞法變量,所以只在定義該變數的詞法作用域中有效,舉例:
實例
#!/usr/bin/perl use feature ' state ' ; sub PrintCount { state $count = 0 ; # 初始化變數 print " counter 值為: $count n " ; $count ++; } for ( 1 . .5 ) { PrintCount ( ) ; }以上程式執行輸出結果為:
counter 值為:0counter 值為:1counter 值為:2counter 值為:3counter 值為:4
註1:state僅能建立閉合作用域為子程序內部的變數。
註2:state是從Perl 5.9.4開始引進的,所以使用前必須加上use。
註3:state可以聲明標量、陣列、哈希。但在聲明數組和哈希時,不能對其初始化(至少Perl 5.14不支援)。
子程序呼叫上下文
子程序呼叫過程中,會根據上下文來傳回不同類型的值,例如以下localtime() 子程序,在標量上下文傳回字串,在列表上下文傳回列表:
實例
#!/usr/bin/perl # 標量上下文my $datestring = localtime ( time ) ; print $datestring ; print " n " ; # 列表上下文( $sec , $min , $hour , $mday , $mon , $year , $wday , $yday , $isdst ) = localtime ( time ) ; printf ( " %d-%d-%d %d:%d :%d " , $year + 1990 , $mon + 1 , $mday , $hour , $min , $sec ) ; print " n " ;以上程式執行輸出結果為:
Sun Jun 12 15:58:09 20162106-6-12 15:58:9