Perl Subroutines (Functions)

Perl subroutines are user-defined functions.

A Perl subroutine is a separate piece of code that performs a specific task, which can reduce repetitive code and make the program easier to read.

A Perl subroutine is a code block that encapsulates a series of operations or calculations, and it can be called repeatedly for reuse in a program.

Perl subroutines help modularize programs, making code easier to understand, maintain, and reuse.

Perl subroutines can appear anywhere in the program, with the following syntax format:

sub subroutine{
   statements;
}

Syntax for calling a subroutine:

subroutine( 参数列表 );

In versions below Perl 5.0, the method to call a subroutine is as follows:

&subroutine( 参数列表 );

In newer versions, although this calling method is still supported, it is not recommended.

Now let's look at a simple example:

Example

#!/usr/bin/perl # Function definition sub Hello{ print "Hello, World!\n"; } # Function call Hello();

Executing the above program produces the following output:

Hello, World!

Passing Parameters to Subroutines

Like other programming languages, Perl subroutines can accept multiple parameters. Subroutine parameters are indicated by the special array @_.

Therefore, the first parameter of the subroutine is $_

Regardless of whether the parameters are scalar or array typed, when users pass parameters to a subroutine, perl calls them by reference by default.

Example

#!/usr/bin/perl # Define a function to calculate the average sub Average{ # Get all passed parameters $n = scalar(@_); $sum = 0; foreach $item (@_){ $sum += $item; } $average = $sum /$n; print 'Passed parameters are : ',"@_\n"; # Print the entire array print "The first parameter value is : $_

Executing the above program produces the following output:

传入的参数为 : 10 20 30
第一个参数值为 : 10
传入参数的平均值为 : 20

Users can change the values of the corresponding actual parameters by modifying the values in the @_ array.

Passing Lists to Subroutines

Since the @_ variable is an array, it can pass lists to subroutines.

However, if we need to pass scalar and array parameters, the list should be placed last, as shown below:

Example

#!/usr/bin/perl # Define a function sub PrintList{ my @list = @_; print "List is : @list\n"; } $a = 10; @b = (1, 2, 3, 4); # List parameter PrintList($a, @b);

The above program merges the scalar and the array, and the output is:

列表为 : 10 1 2 3 4

We can pass multiple arrays and hashes to subroutines, but when doing so, the independent identities (of the arrays and hashes) may be lost. Therefore, we need to use references (introduced in the next chapter) to pass them.

Passing Hashes to Subroutines

When passing a hash to a subroutine, it is copied into @_, and the hash is expanded into a list of key/value pairs.

Example

#!/usr/bin/perl # Method definition sub PrintHash{ my (%hash) = @_; foreach my $key ( keys %hash ){ my $value = $hash{$key}; print "$key : $value\n"; } } %hash = ('name' => 'example', 'age' => 3); # Pass the hash PrintHash(%hash);

Executing the above program produces the following output:

age : 3
name : example

Subroutine Return Values

Like other programming languages, subroutines can use the return statement to return a value.

If no return statement is used, the last statement executed in the subroutine is treated as the return value.

Example

#!/usr/bin/perl # Method definition sub add_a_b{ # Without using return $_[0]+$_[1]; # Using return # return $_[0]+$_[1]; } print add_a_b(1, 2)

Executing the above program produces the following output:

3

In Perl, references can be used to return multiple arrays and hashes. A reference is a scalar value that points to a data structure (such as an array or hash). Through references, we can package multiple arrays and hashes into a single return value to pass back to the calling program. This preserves the independence and integrity of the data structures.

Example

sub return_multiple_data {
    my @array1 = (1, 2, 3);
    my @array2 = ('a', 'b', 'c');
    my %hash1 = ('key1' => 'value1', 'key2' => 'value2');
    my %hash2 = ('foo' => 'bar', 'baz' => 'qux');
   
    return (\@array1, \@array2, \%hash1, \%hash2);
}

my ($array_ref1, $array_ref2, $hash_ref1, $hash_ref2) = return_multiple_data();

# Use references to access the returned data
print "Array 1: @{$array_ref1}\n";
print "Array 2: @{$array_ref2}\n";
print "Hash 1: " . join(", ", %{$hash_ref1}) . "\n";
print "Hash 2: " . join(", ", %{$hash_ref2}) . "\n";

In the above code, the return_multiple_data subroutine returns references to four data structures.

In the calling program, we dereference these references to access the returned arrays and hashes, thereby maintaining their independence and integrity.

The output is:

Array 1: 1 2 3
Array 2: a b c
Hash 1: key1, value1, key2, value2
Hash 2: foo, bar, baz, qux

Private Variables in Subroutines

By default, all variables in Perl are global variables, meaning they can be accessed anywhere in the program.

If we need to set private variables, we can use themy`my` operator to set.

myThe `my` operator is used to create lexically scoped variables.myVariables created by `my` live from the point of declaration until the end of the enclosing scope.

The enclosing scope can be the region within a pair of curly braces, a file, or an if, while, for, foreach, or eval string.

The following example demonstrates how to declare one or more private variables:

sub somefunc {
   my $variable; # $variable 在方法 somefunc() 外不可见
   my ($another, @an_array, %a_hash); #  同时声明多个变量
}

Example

#!/usr/bin/perl # Global variable $string = "Hello, World!"; # Function definition sub PrintHello{ # Private variable of the PrintHello function my $string; $string = "Hello, Example!"; print "String inside function:$string\n"; } # Call the function PrintHello(); print "String outside function:$string\n";

Executing the above program produces the following output:

函数内字符串:Hello, Example!
函数外字符串:Hello, World!

Temporary Assignment of Variables

We can use local to provide a temporary value for a global variable, and the original value is restored after leaving the scope.

Variables defined with local do not exist in the main program, but they exist in the subroutine and in subroutines called by that subroutine. They can be assigned a value at definition, for example:

Example

#!/usr/bin/perl # Global variable $string = "Hello, World!"; sub PrintExample{ # Private variable of the PrintHello function local $string; $string = "Hello, Example!"; # Subroutine called by the subroutine PrintMe(); print "String value inside PrintExample function:$string\n"; } sub PrintMe{ print "String value inside PrintMe function:$string\n"; } sub PrintHello{ print "String value inside PrintHello function:$string\n"; } # Call the function PrintExample(); PrintHello(); print "String value outside the function:$string\n";

Executing the above program produces the following output:

PrintMe 函数内字符串值:Hello, Example!
PrintExample 函数内字符串值:Hello, Example!
PrintHello 函数内字符串值:Hello, World!
函数外部字符串值:Hello, World!

Static Variables

The state operator functions like the static modifier in C; the state keyword makes local variables persistent.

state is also a lexical variable, so it is only valid in the lexical scope where the variable is defined. For example:

Example

#!/usr/bin/perl use feature 'state'; sub PrintCount{ state $count = 0; # Initialize the variable print "The counter value is:$count\n"; $count++; } for (1..5){ PrintCount(); }

Executing the above program produces the following output:

counter 值为:0
counter 值为:1
counter 值为:2
counter 值为:3
counter 值为:4

Note 1: state can only create variables whose enclosing scope is inside a subroutine.

Note 2: state was introduced starting from Perl 5.9.4, so you must add `use` before using it.

Note 3: state can declare scalars, arrays, and hashes. However, when declaring arrays and hashes, they cannot be initialized (at least not supported in Perl 5.14).


Subroutine Call Context

During a subroutine call, different types of values are returned depending on the context. For example, the localtime() subroutine below returns a string in scalar context and a list in list context:

Example

#!/usr/bin/perl # Scalar context my $datestring = localtime( time ); print $datestring; print "\n"; # List context # The value of $year is a count starting from 1900 as the base year ($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time); printf("%d-%d-%d %d:%d:%d",$year+1900,$mon+1,$mday,$hour,$min,$sec); print "\n";

Executing the above program produces the following output:

Sun Jun 12 15:58:09 2016
2106-6-12 15:58:9
Other Extensions