Perl 简明教程
Perl - Subroutines
Perl 子例程或函数是一组共同执行任务的语句。您可以将代码划分为不同的子例程。如何将代码划分为不同的子例程取决于您,但通常从逻辑上讲,这种划分是让每个函数执行一个特定任务。
A Perl subroutine or function is a group of statements that together performs a task. You can divide up your code into separate subroutines. How you divide up your code among different subroutines is up to you, but logically the division usually is so each function performs a specific task.
Perl 可以互换使用子例程、方法和函数这三个术语。
Perl uses the terms subroutine, method and function interchangeably.
Define and Call a Subroutine
Perl 编程语言中子例程定义的一般形式如下 -
The general form of a subroutine definition in Perl programming language is as follows −
sub subroutine_name {
body of the subroutine
}
呼叫 Perl 子例程的通常方式如下 −
The typical way of calling that Perl subroutine is as follows −
subroutine_name( list of arguments );
版本的 Perl 在 5.0 之前,呼叫子例程的語法稍有不同,如下所示。這在最新版本的 Perl 中仍然有效,但不建議使用,因為它會略過子例程原型。
In versions of Perl before 5.0, the syntax for calling subroutines was slightly different as shown below. This still works in the newest versions of Perl, but it is not recommended since it bypasses the subroutine prototypes.
&subroutine_name( list of arguments );
讓我們來看看以下範例,它定義了一個簡單函式並呼叫它。因為 Perl 在執行程式之前會編譯您的程式,所以您在何處宣告您的子例程並不重要。
Let’s have a look into the following example, which defines a simple function and then call it. Because Perl compiles your program before executing it, it doesn’t matter where you declare your subroutine.
#!/usr/bin/perl
# Function definition
sub Hello {
print "Hello, World!\n";
}
# Function call
Hello();
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
Hello, World!
Passing Arguments to a Subroutine
您可以將各種參數傳遞給子例程就像在任何其他程式語言中一樣,並且可以在函式中使用特殊陣列 @ . Thus the first argument to the function is in $ [0] 存取這些參數,第二個在 $_[1] 中,等等。
You can pass various arguments to a subroutine like you do in any other programming language and they can be acessed inside the function using the special array @. Thus the first argument to the function is in $[0], the second is in $_[1], and so on.
您可以傳遞陣列和雜湊作為參數,就像傳遞任何純量一樣,但通常傳遞多個陣列或雜湊會導致它們失去各自的識別碼。因此,我們將使用參考(在下一章中說明)來傳遞任何陣列或雜湊。
You can pass arrays and hashes as arguments like any scalar but passing more than one array or hash normally causes them to lose their separate identities. So we will use references ( explained in the next chapter ) to pass any array or hash.
讓我們嘗試以下範例,它會取得數字清單然後列印它們的平均值 −
Let’s try the following example, which takes a list of numbers and then prints their average −
#!/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);
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
Average for the given numbers : 20
Passing Lists to Subroutines
因為 @_ 變數是一個陣列,所以它可用於對子例程提供清單。但是,由於 Perl 接受並分析清單和陣列的方式,因此從 @_ 中提取個別元素可能會很困難。如果您必須傳遞清單以及其他純量參數,請將清單作為最後一個參數,如下所示 −
Because the @_ variable is an array, it can be used to supply lists to a subroutine. However, because of the way in which Perl accepts and parses lists and arrays, it can be difficult to extract the individual elements from @_. If you have to pass a list along with other scalar arguments, then make list as the last argument as shown below −
#!/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);
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
Given list is 10 1 2 3 4
Passing Hashes to Subroutines
當您將雜湊提供給接受清單的子例程或運算子時,雜湊會自動轉換為一對關鍵字/值的清單。例如 −
When you supply a hash to a subroutine or operator that accepts a list, then hash is automatically translated into a list of key/value pairs. For example −
#!/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);
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
name : Tom
age : 19
Returning Value from a Subroutine
您可以從子例程傳回值,就像在任何其他程式語言中一樣。如果您沒有從子例程傳回值,則子例程中最後執行的任何計算結果也會自動作為回傳值。
You can return a value from subroutine like you do in any other programming language. If you are not returning a value from a subroutine then whatever calculation is last performed in a subroutine is automatically also the return value.
您可以從子例程傳回陣列和雜湊,就像傳回任何純量一樣,但通常傳回多個陣列或雜湊會導致它們失去各自的識別碼。因此,我們將使用參考(在下一章中說明)從函式傳回任何陣列或雜湊。
You can return arrays and hashes from the subroutine like any scalar but returning more than one array or hash normally causes them to lose their separate identities. So we will use references ( explained in the next chapter ) to return any array or hash from a function.
讓我們嘗試以下範例,它會取得數字清單然後傳回它們的平均值 −
Let’s try the following example, which takes a list of numbers and then returns their average −
#!/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";
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
Average for the given numbers : 20
Private Variables in a Subroutine
預設情況下,Perl 中的所有變數都是全域變數,這表示可以在程式的任何地方存取這些變數。但是,您可以使用 my 運算子在任何時候建立稱為 lexical variables 的 private 變數。
By default, all variables in Perl are global variables, which means they can be accessed from anywhere in the program. But you can create private variables called lexical variables at any time with the my operator.
my 運算子將變數限定在可以用來使用和存取它的特定程式碼區域。在那個區域之外,無法使用或存取這個變數。這個區域稱為它的範圍。詞彙範圍通常是一段包含大括號的程式碼區塊,例如那些定義子例程主體或標記 if、while、for、foreach 和 eval 陳述式的程式碼區塊。
The my operator confines a variable to a particular region of code in which it can be used and accessed. Outside that region, this variable cannot be used or accessed. This region is called its scope. A lexical scope is usually a block of code with a set of braces around it, such as those defining the body of the subroutine or those marking the code blocks of if, while, for, foreach, and eval statements.
以下是範例,展示如何使用 my 運算子定義單一或多個私有變數 −
Following is an example showing you how to define a single or multiple private variables using my operator −
sub somefunc {
my $variable; # $variable is invisible outside somefunc()
my ($another, @an_array, %a_hash); # declaring many variables at once
}
讓我們檢查以下範例,以區分全域和私有變數 −
Let’s check the following example to distinguish between global and private variables −
#!/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";
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
Inside the function Hello, Perl!
Outside the function Hello, World!
Temporary Values via local()
local 通常用於必須讓呼叫的子例程可見變數的目前值。local 只會將暫時值提供給全域(表示封裝)變數。這稱為動態範圍。使用更類似於 C 的 auto 宣告的 my 來執行詞彙範圍。
The local is mostly used when the current value of a variable must be visible to called subroutines. A local just gives temporary values to global (meaning package) variables. This is known as dynamic scoping. Lexical scoping is done with my, which works more like C’s auto declarations.
如果將多個變數或表達式提供給 local,必須將它們放在括號中。這個運算子會儲存那些變數在隱藏佇列中參數清單的目前值,然後在離開區塊、子例程或 eval 時復原它們。
If more than one variable or expression is given to local, they must be placed in parentheses. This operator works by saving the current values of those variables in its argument list on a hidden stack and restoring them upon exiting the block, subroutine, or eval.
讓我們檢查以下範例,以區分全域和 local 變數 −
Let’s check the following example to distinguish between global and local variables −
#!/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";
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
Inside the function PrintMe Hello, Perl!
Inside the function PrintHello Hello, Perl!
Outside the function Hello, World!
State Variables via state()
还有一种词法变量,它类似于私有变量,但它们保持其状态,并且在多次调用子例程时不会被重新初始化。这些变量使用 state 运算符定义,并从 Perl 5.9.4 开始提供。
There are another type of lexical variables, which are similar to private variables but they maintain their state and they do not get reinitialized upon multiple calls of the subroutines. These variables are defined using the state operator and available starting from Perl 5.9.4.
让我们检查以下示例来演示 state 变量的使用 -
Let’s check the following example to demonstrate the use of state variables −
#!/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();
}
當以上程式執行時,會產生以下結果 −
When above program is executed, it produces the following result −
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 之前,您必须这样编写它 -
Prior to Perl 5.10, you would have to write it like this −
#!/usr/bin/perl
{
my $count = 0; # initial value
sub PrintCount {
print "Value of counter is $count\n";
$count++;
}
}
for (1..5) {
PrintCount();
}
Subroutine Call Context
子例程或语句的上下文被定义为预期的返回值类型。这使您可以使用一个函数来返回不同的值,具体取决于用户期望接收的值。例如,以下 localtime() 在标量上下文中调用时返回一个字符串,但在列表上下文中调用时返回一个列表。
The context of a subroutine or statement is defined as the type of return value that is expected. This allows you to use a single function that returns different values based on what the user is expecting to receive. For example, the following localtime() returns a string when it is called in scalar context, but it returns a list when it is called in list context.
my $datestring = localtime( time );
在此示例中,$timestr 的值现在是一个由当前日期和时间组成的字符串,例如 Thu Nov 30 15:21:33 2000。相反 -
In this example, the value of $timestr is now a string made up of the current date and time, for example, Thu Nov 30 15:21:33 2000. Conversely −
($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);
现在各个变量包含 localtime() 子例程返回的相应值。
Now the individual variables contain the corresponding values returned by localtime() subroutine.