Perl - 第十二章 | Perl 子程序(函數)
Perl子例程或函數是一起執行任務的一組語句。你可以將程式碼分成單獨的子例程。如何在不同的子例程之間劃分程式碼取決於你,但是從邏輯上來說,劃分通常是使每個函數執行特定任務。
定義並調用子程序
Perl編程語言中子例程定義的一般形式如下:
1 | sub subroutine_name { |
調用該Perl子例程的典型方式如下:
1 | subroutine_name( list of arguments ); |
在5.0之前的Perl版本中,調用子例程的語法略有不同,如下所示。這仍然可以在最新版本的Perl中使用,但不建議這樣做,因為它會繞過子例程原型。
1 | &subroutine_name( list of arguments ); |
讓我們看一下下面的範例,該範例定義一個簡單的函數,然後調用它。因為Perl在執行程序之前先對其進行編譯,所以在哪裡聲明子例程都沒有關係。
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | Hello, World! |
向子程序傳遞參數
你可以像在任何其他編程語言中一樣將各種參數傳遞給子例程,並且可以使用特殊數組@_在函數內部訪問它們。因此,函數的第一個參數位於$ _ [0]中,第二個參數位於$ _ [1]中,依此類推。
你可以像任何標量一樣將數組和散列作為參數傳遞,但是傳遞多個數組或散列通常會導致它們失去各自的標識。因此,我們將使用引用(在下一章中進行說明)來傳遞任何數組或哈希。
讓我們嘗試以下範例,該範例獲取一個數字列表,然後輸出其平均值:
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | 傳入的參數為 : 10 20 30 |
向子程序傳遞列表
由於@_變量是一個數組,因此可以用來為子例程提供列表。但是,由於Perl接受和解析列表和數組的方式,可能很難從@_中提取單個元素。如果你必須將列表與其他標量參數一起傳遞,則將list作為最後一個參數,如下所示:
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | 列表為 : 10 1 2 3 4 |
註:我們可以向子程序傳入多個數組和哈希,但是在傳入多個數組和哈希時,會導致丟失獨立的標識。所以我們需要使用引用(後面會學到)來傳遞。
向子程序傳遞哈希
當你向接受列表的子例程或運算符提供哈希值時,哈希值將自動轉換為鍵/值對列
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | age : 3 |
子程序返回值
子程序可以向其他編程語言一樣使用 return 語句來返回函數值。
如果沒有使用 return 語句,則子程序的最後一行語句將作為返回值。
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | 3 |
註:子程序中我們可以返回標量,數組和哈希,但是在返回多個數組和哈希時,會導致丟失獨立的標識。所以我們需要使用引用(後面會學到)來返回多個數組和函數。
子程序的私有變量
預設情況下,Perl中所有的變量都是全局變量,這就是說變量在程序的任何地方都可以調用。
如果我們需要設置私有變量,可以使用my操作符來設置。
my操作符用於建立詞法作用域變量,通過my建立的變量,存活於聲明開始的地方,直到閉合作用域的結尾。
閉合作用域指的可以是一對花括號中的區域,可以是一個文件,也可以是一個 if, while, for, foreach, eval字符串。
如何聲明一個或多個私有變量:
1 | sub somefunc { |
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | 函數內字符串:Hello, Morosedog! |
變量的臨時賦值
我們可以使用local為全局變量提供臨時的值,在退出作用域後將原來的值還回去。
local定義的變量不存在於主程序中,但存在於該子程序和該子程序調用的子程序中。定義時可以給其賦值,如:
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | PrintMe 函數內字符串值:Hello, Morosedog! |
靜態變量
state操作符功能類似於C裡面的static修飾符,state關鍵字將局部變量變得持久。
state也是詞法變量,所以只在定義該變量的詞法作用域中有效,舉個例子:
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | counter 值為:0 |
注1:state僅能建立閉合作用域為子程序內部的變量。
注2:state是從Perl 5.9.4開始引入的,所以使用前必須加上use。
注3:state可以聲明標量、數組、哈希。但在聲明數組和哈希時,不能對其初始化(至少Perl 5.14不支持)。
子程序調用上下文
子程序調用過程中,會根據上下文來返回不同類型的值,比如以下 localtime() 子程序,在標量上下文返回字符串,在列表上下文返回列表:
1 | #!/usr/bin/perl |
這將產生以下結果:
1 | Mon Mar 15 10:08:01 2021 |