這兩個術語可以在Perl函數和子程序互換使用。函數是一個命名的代碼塊,通常是用於處理指定到的輸出值的輸入值,雖然這並不總是這樣。例如,打印函數需要變量和靜態文本,並打印在屏幕上的值。
子程序,如變量,可以聲明(不用定義他們來做了什麼)或聲明和定義。簡單地聲明一個子程序,可以使用下列形式之一:
sub NAME sub NAME PROTO sub NAME ATTRS sub NAME PROTO ATTRS
其中,NAME是您所創建的子程序的名稱,Proto是期望的子程序調用時的參數的原型,ATTRS是一個屬性的子程序呈現。
如果你想聲明和定義一個函數,那麼你就需要包括塊定義其操作:
sub NAME BLOCK sub NAME PROTO BLOCK sub NAME ATTRS BLOCK sub NAME PROTO ATTRS BLOCK
您還可以創建匿名函數 - 冇有名字的子程序省略NAME組件:
sub BLOCK sub PROTO BLOCK sub ATTRS BLOCK sub PROTO ATTRS BLOCK
要調用一個函數,你可以使用下列形式之一:
NAME NAME LIST NAME (LIST) &NAME
舉一個簡單的例子,一個簡單的子程序:
sub message { print "Hello!\n"; # by www.gitbook.net }
第一個參數傳遞給子程序是在函數的$_[0],第二個參數是$_[1]等等。這個簡單的函數例如,將兩個數相加並輸出結果:
sub add { $result = $_[0] + $_[1]; print "The result was: $result\n"; }
要調用的子程序,得到的結果:
add(1,2);
前麵的子程序是相當簡單的,但如果你想已經命名參數嗎? 簡單的答案是指定的值@_的變量列表:
sub add { ($numbera, $numberb) = @_; $result = $numbera + $numberb; print "The result was: $result\n"; }
shift 函數是一個堆棧,操作數由Perl支持。shift 函數返回一個數組的第一個元素(刪除)。例如:
sub add { my $numbera = shift; my $numberb = shift; #by www.gitbook.net my $result = $numbera + $numberb; print "The result was: $result\n"; }
效果是完全一樣的,因為我們已經證明,但以不同的方式,我們剛剛得到的參數。
任何塊的返回值,包括那些在子程序中使用,作為最後計算的表達式的值。 對於為例,這裡的返回值是計算結果。
sub myfunc { $_[0]+$_[1]; }
您也可以顯式地返回一個值,使用return關鍵字:
sub myfunc { if (@_) { return $_[0]+$_[1]; } else { return 0; } }
調用時,立即返回,而終止當前的子程序並返回值給調用者。如果你不指定一個值,則返回值是undef。
一個子程序或語句的上下文中被定義為預期的返回值的類型。這使您可以使用一個單一的函數,返回不同的值,根據用戶期望接收。例如,下麵的兩個調用的getpwent函數返回一個列表或一個標量,根據分配使用:
$name = getpwent(); ($name, $passwd, $uid, $gid, $quota, $comment, %gcos, $dir, $shell) = getpwent();
在第一種情況下,用戶的期望由該函數返回一個標量值,因為返回值將被賦值。在第二種情況下,用戶期望的陣列作為返回值再次由於已被指定為要插入到的信息的標量的列表。
下麵是另一個例子,從內置Perl函數顯示靈活性:
my $timestr = localtime(time);
在這個例子中,當前的日期和時間所組成的字串$timestr的值。例如,2000年11月30日15時21分33秒,星期四。相反的:
($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);
現在,單個變量包含相應的值返回的本地時間。
注: 左值的子程序仍然是實驗性的實施可能會在未來Perl版本中有所改變。
從子程序返回一個可修改的值是有可能的。要做到這一點,你必須聲明的子程序返回一個左值。參見下麵的例子
my $val; sub canmod : lvalue { # return $val; this doesn't work, don't say "return" $val; } sub nomod { $val; }
現在看到以下結果:
canmod() = 5; # assigns to $val in the above subroutine nomod() = 5; # ERROR
因為@_變量是一個數組,它可以被用來提供列表子程序。然而,因為在其中Perl接受並解析列表和數組的方式,它可以是難以提取從@_的單個元素。以下是有效的。
mysub(1,2,3); @args = (2,3); mysub(1,@args); @args = (1,2,3); mysub(@args);
最後,當我們收到的值@_變量,我們可以不承認如果我們通過一個數組或兩個值數組,因為它最後要合並成一個。
如果你想使用並確定傳遞給Perl的個彆列表,那麼你需要使用參考:
(@listc, @listd) = simplesort(\@lista, \@listb);
開頭的\字符告訴Perl提供參考,指針,數組的。 引用是實際上隻是一個標量,因此,我們可以找出每個列表分配給每個陣列在我們的子程序。現在,你可以寫子程序如下:
sub simplesort { my ($listaref, $listbref ) = @_; # De-reference the array list - by www.gitbook.net my (@lista) = @$listaref; my (@listb) = @$listbref; #by www.gitbook.net # Now you can play with both arrays. }
當你提供了一個散列到一個子程序或運算符接受一個列表,哈希會自動翻譯成鍵/值對的列表。例如:
%hash = ('name' => 'Tom', 'age' => 19); print %hash;
這將輸出 .nameTomage19. 然而,同樣的過程相反的,這樣我們就可以提取一個列表,將其轉換為一個哈希:
sub display_hash { my (%hash) = @_; foreach (%hash) { print "$_ => $hash{$_}\n"; } }
在這種情況下,我們輸出的鍵/值對的哈希正常,顯示每對它自己的行。正如數組,如果你希望挑選出一個單一的哈希值的參數列表。下麵的工作,因為我們提取的哈希最後一個元素:
sub display_has_regexp { my ($regex, %hash) = @_; ... }
而這不會,因為我們嘗試提取的哈希(有將是一個額外的元素,和Perl會不知道如何分配到哈希):
sub display_has_regexp { my (%hash, $regex) = @_; ... }
如果你想使用多個哈希值,然後使用引用。例如,下麵的子程序返回的關鍵相交的兩個哈希:
sub intersection { my ($hasha, $hashb) = @_; my %newhash; foreach my $key (keys %{$hasha}) { $newhash{$key} = $$hasha{$key} if (exists $$hashb{$key}); } #by www.gitbook.net return %newhash; }
要使用子程序:
%hasha = ('a' => 'b',
'b' => 'b',
'c' => 'b');
%hashb = ('b' => 'b',
'c' => 'b',
'd' => 'b');
%newhash = intersection(\%hasha, \%hashb);