一、子程式的概念:
子程式就是函數,是一段執行特殊任務的分離的代碼,使用子程式可以提高代碼的複用度;從使用的角度來分,可以把子程式分為四種:系統函數、使用者子定義函數、有參函數、無參函數;
Perl的子程式可以出現在程式中的任何地方;子程式的聲明使用關鍵字sub來做;聲明無參函數和有參函數的文法如下:
sub 子程式名;
sub 子程式名(參數列表);
只有聲明而沒有定義的子程式可以用於列表;定義子程式就是在子程式的聲明後面加上一段代碼塊;無參函數和有參函數的定義如下:
sub 子程式名
{
#The body of this function
}
sub 子程式名(參數列表)
{
#The body of this function
}
也可以定義匿名子程式,文法如下:
$FunctionRef = sub { #The body of this function };
定義匿名子程式時,最後面的分號是必須的,因為這是一個指派陳述式;
還可以定義空的子程式,文法如下:
sub 子程式名 {}
sub 子程式名(參數列表) {}
空的子程式什麼都不做,沒有實際意義,表示這些子程式的功能暫時不明確,優待以後實現或擴充;
二、子程式的調用:
Perl中,子程式的調用文法有多種,不同的調用文法對傳給子程式的參數有不同的影響;數組“@_”是Perl中的一個重要的數組,也是一個內建數組,它的作用是用於存放子程式所收到的參數列表;
子程式的調用方法從調用方式上來分,可以分為直接調用和間接調用;使用引用來調用子程式的方式稱為間接調用;不使用引用來調用子程式的方式稱為直接調用;
在Perl5之前(不包括Perl5)的版本中,調用子程式的時候要求在子程式名前面加上位與運算子“&”,以告訴Perl解譯器讓這個子程式採用自己的參數列表;在Perl5中當然可以繼續這樣使用,而且功能一樣,但是在Perl5新增加的一種引用功能中,用子程式引用的方式來調用子程式的文法如下:
&$FunRef(參數列表);
這個時候位與運算子&會告訴Perl解譯器從子程式列表中尋找子程式引用的地址;所以在Perl5中最好不要再使用位與運算子和子程式引用方式來調用子程式;它會與老版本中的位與運算子在代碼閱讀上產生不易理解的現象;
子程式調用方法列表:
1、SubFunName;
直接調用,把所在塊的全域@_數組作為參數列表傳遞給被調子程式;
2、SubFunName(參數列表);
直接調用,產生@_數組的局部備份,設定為參數表的標量值;
3、SubFunName 參數列表;
直接調用,產生@_數組的局部備份,設定為參數表的標量值;這個時候調用的子程式必須是事先已經聲明過
的子程式;
4、&SubFunName;
直接調用,把所在塊的全域@_數組作為參數表傳遞給被調子程式;
5、&SubFunName(參數列表);
直接調用,產生@_數組的局部備份,設定為參數表的標量值;
6、&$SubFunRef;
間接調用,用子程式的引用來調用子程式,位與運算子&是必須的;把所在塊的全域@_數組作為參數列表傳遞
給被調子程式;
7、&$SubFunRef 參數列表;
間接調用,產生@_數組的局部備份,數組值與參數表的標量值相等;
在Perl5中一般使用直接調用的方式來調用子程式就可以了,只要調用子程式時傳遞的參數符合子程式定義時的參數列表中的參數的規則就可以;如果調用子程式時,傳遞的參數不符合該子程式在定義時給出的參數列表中的參數的規則的話,程式就會有語法錯誤,這種情況下,解決該問題的方法就是在調用子程式時在該子程式名前面加上按位與運算子“&”,以告訴Perl解譯器,強制使用傳遞給該子程式的實際參數列表或者是強制使用所在塊的全域@_數組作為實際參數列表傳遞給該子程式;這就是按位與運算子“&”的用途;通過在子程式名稱前加按位與運算子(&)調用,可以在任一運算式中調用子程式;
調用子程式時要注意以下幾點:
◆ 如果沒有參數列表,並且在調用子程式時使用了按位與運算子&,則所在塊的全域@_數組的備份傳遞給子程式;
◆ 如果調用子程式時使用了參數列表(實參列表),則@_數組產生為參數列表的局部備份;
◆ 如果把按位與運算子&與實際參數列表一起使用,並且實際參數列表放在圓括弧內,則實際參數列表傳遞給被調用的子程式,並且備份在局部@_數組中;
◆ 如果實際參數列表不放在圓括弧中,則全域@_數組的備份就會被傳遞給被調用的子程式;
◆ 實現遞迴子程式時需要注意:除了不被子程式改變的變數之外,其餘的變數都必須是局部的,而且還要含有結束調用子程式本身的遞迴結束條件;
三、子程式的參數列表:
如果函數調用的後面跟著一個用圓括弧括起來的列表,則在函數調用期間,這個列表將被Perl解譯器自動備份儲存在Perl的內建特殊陣列變數@_中,函數可以訪問這個特殊的變數,以確定參數的個數及賦值;
在Perl中,不帶參數列表聲明和定義的子程式在被調用時可以不限制傳遞給該子程式的參數的個數和類型,而帶參數列表聲明和定義的子程式在被調用的時候必須按照聲明和定義時給出的參數規則來調用,否則會出現調用錯誤。
在聲明或定義函數時,函數名稱後面的參數列表稱為形式參數(簡稱形參);在調用函數時,函數名稱後面的參數列表稱為實際參數(簡稱實參);
聲明或定義子程式時,形參列表定義了子程式所需要使用的參數個數和類型。定義形參列表時,要把每個參數的類型指示符放在圓括弧中,每個類型指示符定義這個位置上所需要的參數的類型。
參數列表中使用分號(;)把必選參數和選擇性參數分開,分號前面列出的參數是必選參數,分號後面列出的參數是選擇性參數;
在Perl中,如果聲明或定義函數參數前面有反斜線“/”,就表示要寫入內建特殊數組@_中的是引用變數。輸入的參數的類型必須與聲明或定義時給出的對應參數的類型相同;即,有反斜線的形參傳遞的是變數的引用;
參數列表樣本:
1、():
不要求有參數,即:可以不接受任何參數,也可以接受任意類型和個數的參數;
2、($):
要求只有一個參數,並且必須是個標量參數;
3、($;/%):
要求有一個必選參數(標量)和一個選擇性參數(雜湊變數的引用);分號前面的是一個必選參數,分號後面的那個是一個選擇性參數,但這個選擇性參數必須是對一個雜湊變數的引用;結果是必選參數和雜湊變數的引用被存入數組@_中;
4、($$$@):
要求前面的三個參數是標量參數,後面其餘的參數放在後面的數群組類型變數中;
5、(/@/%$;$$) :
要求前三個參數是必選參數,後兩個參數是選擇性參數;第一個參數是數組的引用,第二個參數是雜湊變數的引用,第三個參數是上下文中的標量變數;後兩個選擇性參數是標量變數;
如果聲明或定義的參數前面不加反斜線,則形參強制類型指定符上下文成為實參;比如:形參是標量類型指定符,但是實參卻是數組,則對實參採用標量上下文,即把數組的長度傳遞給子程式,而不是數組值;