Perl - 子程式



Perl 子程式或函式是一組執行任務的語句。您可以將程式碼劃分為單獨的子程式。如何將程式碼劃分為不同的子程式取決於您自己,但邏輯上劃分通常是讓每個函式執行特定的任務。

Perl 交換使用子程式、方法和函式這幾個術語。

定義和呼叫子程式

Perl 程式語言中子程式定義的一般形式如下:

sub subroutine_name {
   body of the subroutine
}

呼叫 Perl 子程式的典型方法如下:

subroutine_name( list of arguments );

在 5.0 之前的 Perl 版本中,呼叫子程式的語法略有不同,如下所示。這在最新版本的 Perl 中仍然有效,但不建議使用,因為它繞過了子程式原型。

&subroutine_name( list of arguments );

讓我們看一下下面的示例,它定義了一個簡單的函式,然後呼叫它。因為 Perl 在執行程式之前會編譯程式,所以您在何處宣告子程式並不重要。

#!/usr/bin/perl

# Function definition
sub Hello {
   print "Hello, World!\n";
}

# Function call
Hello();

執行上述程式時,會產生以下結果:

Hello, World!

向子程式傳遞引數

您可以像在任何其他程式語言中一樣向子程式傳遞各種引數,並且可以使用特殊的陣列 @_ 在函式內部訪問它們。因此,函式的第一個引數在 $_[0] 中,第二個引數在 $_[1] 中,依此類推。

您可以像任何標量一樣傳遞陣列和雜湊作為引數,但是傳遞多個數組或雜湊通常會導致它們丟失其單獨的身份。因此,我們將使用引用(下一章中解釋)來傳遞任何陣列或雜湊。

讓我們嘗試以下示例,它接收數字列表,然後列印它們的平均值:

#!/usr/bin/perl

# Function definition
sub Average {
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_) {
      $sum += $item;
   }
   $average = $sum / $n;

   print "Average for the given numbers : $average\n";
}

# Function call
Average(10, 20, 30);

執行上述程式時,會產生以下結果:

Average for the given numbers : 20

向子程式傳遞列表

因為 @_ 變數是一個數組,所以它可以用來向子程式提供列表。但是,由於 Perl 接受和解析列表和陣列的方式,因此很難從 @_ 中提取各個元素。如果您必須與其他標量引數一起傳遞列表,則將列表作為最後一個引數,如下所示:

#!/usr/bin/perl

# Function definition
sub PrintList {
   my @list = @_;
   print "Given list is @list\n";
}
$a = 10;
@b = (1, 2, 3, 4);

# Function call with list parameter
PrintList($a, @b);

執行上述程式時,會產生以下結果:

Given list is 10 1 2 3 4

向子程式傳遞雜湊

當您向接受列表的子程式或運算子提供雜湊時,雜湊會自動轉換為鍵/值對列表。例如:

#!/usr/bin/perl

# Function definition
sub PrintHash {
   my (%hash) = @_;

   foreach my $key ( keys %hash ) {
      my $value = $hash{$key};
      print "$key : $value\n";
   }
}
%hash = ('name' => 'Tom', 'age' => 19);

# Function call with hash parameter
PrintHash(%hash);

執行上述程式時,會產生以下結果:

name : Tom
age : 19

從子程式返回值

您可以像在任何其他程式語言中一樣從子程式返回值。如果您沒有從子程式返回值,則子程式中最後執行的任何計算也自動成為返回值。

您可以像任何標量一樣從子程式返回陣列和雜湊,但是返回多個數組或雜湊通常會導致它們丟失其單獨的身份。因此,我們將使用引用(下一章中解釋)從函式返回任何陣列或雜湊。

讓我們嘗試以下示例,它接收數字列表,然後返回它們的平均值:

#!/usr/bin/perl

# Function definition
sub Average {
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_) {
      $sum += $item;
   }
   $average = $sum / $n;

   return $average;
}

# Function call
$num = Average(10, 20, 30);
print "Average for the given numbers : $num\n";

執行上述程式時,會產生以下結果:

Average for the given numbers : 20

子程式中的私有變數

預設情況下,Perl 中的所有變數都是全域性變數,這意味著可以從程式的任何位置訪問它們。但是,您可以隨時使用 my 運算子建立稱為 詞法變數私有變數。

my 運算子將變數限制在可以使用和訪問的特定程式碼區域內。在此區域之外,無法使用或訪問此變數。此區域稱為其作用域。詞法作用域通常是一塊程式碼,周圍有一組花括號,例如定義子程式主體或標記 if、while、for、foreach、eval 語句的程式碼塊的花括號。

以下是一個示例,向您展示如何使用 my 運算子定義單個或多個私有變數:

sub somefunc {
   my $variable; # $variable is invisible outside somefunc()
   my ($another, @an_array, %a_hash); # declaring many variables at once
}

讓我們檢查以下示例以區分全域性變數和私有變數:

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

# Function definition
sub PrintHello {
   # Private variable for PrintHello function
   my $string;
   $string = "Hello, Perl!";
   print "Inside the function $string\n";
}
# Function call
PrintHello();
print "Outside the function $string\n";

執行上述程式時,會產生以下結果:

Inside the function Hello, Perl!
Outside the function Hello, World!

透過 local() 獲取臨時值

local 主要用於當前變數的值必須對呼叫的子程式可見的情況。local 只是為全域性(表示包)變數提供臨時值。這稱為動態作用域。詞法作用域由 my 完成,其工作方式更類似於 C 的 auto 宣告。

如果向 local 提供多個變數或表示式,則必須將它們放在括號中。此運算子透過將其引數列表中的這些變數的當前值儲存在隱藏的堆疊上,並在退出塊、子程式或 eval 時恢復它們來工作。

讓我們檢查以下示例以區分全域性變數和區域性變數:

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

sub PrintHello {
   # Private variable for PrintHello function
   local $string;
   $string = "Hello, Perl!";
   PrintMe();
   print "Inside the function PrintHello $string\n";
}
sub PrintMe {
   print "Inside the function PrintMe $string\n";
}

# Function call
PrintHello();
print "Outside the function $string\n";

執行上述程式時,會產生以下結果:

Inside the function PrintMe Hello, Perl!
Inside the function PrintHello Hello, Perl!
Outside the function Hello, World!

透過 state() 獲取狀態變數

還有另一種型別的詞法變數,它們類似於私有變數,但它們會維護其狀態,並且在多次呼叫子程式時不會重新初始化。這些變數使用 state 運算子定義,並且從 Perl 5.9.4 開始可用。

讓我們檢查以下示例以演示 state 變數的使用:

#!/usr/bin/perl

use feature 'state';

sub PrintCount {
   state $count = 0; # initial value

   print "Value of counter is $count\n";
   $count++;
}

for (1..5) {
   PrintCount();
}

執行上述程式時,會產生以下結果:

Value of counter is 0
Value of counter is 1
Value of counter is 2
Value of counter is 3
Value of counter is 4

在 Perl 5.10 之前,您需要這樣編寫:

#!/usr/bin/perl

{
   my $count = 0; # initial value

   sub PrintCount {
      print "Value of counter is $count\n";
      $count++;
   }
}

for (1..5) {
   PrintCount();
}

子程式呼叫上下文

子程式或語句的上下文定義為預期返回的值型別。這允許您使用單個函式根據使用者期望接收的內容返回不同的值。例如,以下 localtime() 在標量上下文中呼叫時返回字串,但在列表上下文中呼叫時返回列表。

my $datestring = localtime( time );

在此示例中,$timestr 的值現在是一個由當前日期和時間組成的字串,例如 Thu Nov 30 15:21:33 2000。相反:

($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);

現在各個變數包含 localtime() 子程式返回的相應值。

廣告

© . All rights reserved.