Perl 子程式(函數)
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 "传入参数的平均值为 : $average\n"; # 打印平均值 } # 调用函数 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' => 'php', 'age' => 3); # 传递哈希 PrintHash(%hash);
以上程式執行輸出結果為:
age : 3 name : php
子程式傳回值
子程式可以向其他程式語言一樣使用 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, php!"; print "函数内字符串:$string\n"; } # 调用函数 PrintHello(); print "函数外字符串:$string\n";
以上程式執行輸出結果為:
函数内字符串:Hello, php! 函数外字符串:Hello, World!
變數的暫存賦值
#我們可以使用local 為全域變數提供臨時的值,在退出作用域後將原來的值還回去。
local 定義的變數不存在於主程式中,但存在於該子程式和該子程式呼叫的子程式中。定義時可以給其賦值,如:
#!/usr/bin/perl # 全局变量 $string = "Hello, World!"; sub Printphp{ # PrintHello 函数私有变量 local $string; $string = "Hello, php!"; # 子程序调用的子程序 PrintMe(); print "Printphp 函数内字符串值:$string\n"; } sub PrintMe{ print "PrintMe 函数内字符串值:$string\n"; } sub PrintHello{ print "PrintHello 函数内字符串值:$string\n"; } # 函数调用 Printphp(); PrintHello(); print "函数外部字符串值:$string\n";
以上程式執行輸出結果為:
PrintMe 函数内字符串值:Hello, php! Printphp 函数内字符串值:Hello, php! 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 值为:0 counter 值为:1 counter 值为:2 counter 值为:3 counter 值为: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 2016 2106-6-12 15:58:9