PERL Subrountines

he two terms function and subroutine are used interchangeably in Perl. A function is a named code block that is generally intended to process specified input values into an output value, although this is not always the case. For example, the print function takes variables and static text and prints the values on the screen.
  • Like many languages, Perl provides for user-defined subroutines.
  • These may be located anywhere in the main program.
  • Loaded in from other files via the do, require, or use keywords.
  • Any arguments passed in show up in the array @_.
  • A return statement may be used to exit a subroutine.
  • If no return is found and if the last statement is an expression, its value is returned.
  • If the last statement is a loop control structure like a foreach or a while , the returned value is unspecified.
  • Subroutines can return Scalar, Array or Hash.
Subroutines, like variables, can be declared (without defining what they do) or declared and defined. To simply declare a subroutine, you use one of the following forms:
sub NAME
sub NAME PROTO
sub NAME ATTRS
sub NAME PROTO ATTRS
where NAME is the name of the subroutine you are creating, PROTO is the prototype for the arguments the subroutine should expect when called, and ATTRS is a list of attributes that the subroutine exhibits.
If you want to declare and define a function, then you need to include the BLOCK that defines its operation:
sub NAME BLOCK
sub NAME PROTO BLOCK
sub NAME ATTRS BLOCK
sub NAME PROTO ATTRS BLOCK
You can also create anonymous subroutines – subroutines without a name by omitting the NAME component:
sub BLOCK
sub PROTO BLOCK
sub ATTRS BLOCK
sub PROTO ATTRS BLOCK
To call a function you would use one of the following forms:
NAME
NAME LIST
NAME (LIST)
&NAME
To give a quick example of a simple subroutine:
sub message
{
print "Hello!n";
}

Function Arguments

The first argument you pass to the subroutine is available within the function as $_[0], the second argument is $_[1], and so on. For example, this simple function adds two numbers and prints the result:
sub add
{
$result = $_[0] + $_[1];
print "The result was: $resultn";
}
To call the subroutine and get a result:
add(1,2);
The preceding subroutine is fairly simple, but what if you wanted to have named arguments? The simple answer is to assign the values of @_ to a list of variables:
sub add
{
($numbera, $numberb) = @_;

$result = $numbera + $numberb;
print "The result was: $resultn";
}
The shift function is one of the .stack. operands supported by Perl. The shift function returns (and removes) the first element of an array. For example:
sub add
{
my $numbera = shift;
my $numberb = shift;

my $result = $numbera + $numberb;
print "The result was: $resultn";
}
The effect is exactly the same as we have shown earlier but we have just obtained the arguments in a different way.

Return Values from a Function

The return value of any block, including those used in subroutines, is taken as the value of the last evaluated expression. For exampl,e the return value here is the result of the calculation.:
sub myfunc
{
$_[0]+$_[1];
}
You can also explicitly return a value using the return keyword:
sub myfunc
{
if (@_)
{
return $_[0]+$_[1];
}
else
{
return 0;
}
}
When called, return immediately terminates the current subroutine and returns the value to the caller. If you don’t specify a value then the return value is undef.

A Function Call Context

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 two calls to the getpwent function return a list or a scalar, according to what was used in the assignation:
$name = getpwent();
($name, $passwd, $uid, $gid, $quota,
$comment, %gcos, $dir, $shell) = getpwent();
In the first case, the user expects a scalar value to be returned by the function, because that is what the return value is being assigned to. In the second case, the user expects an array as the return value, again because a list of scalars has been specified for the information to be inserted into.
Here’s another example, again from the built-in Perl functions, that shows the flexibility:
my $timestr = localtime(time);
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);
Now the individual variables contain the corresponding values returned by localtime.

Lvalue subroutines

WARNING: Lvalue subroutines are still experimental and the implementation may change in future versions of Perl.
It is possible to return a modifiable value from a subroutine. To do this, you have to declare the subroutine to return an lvalue. See the following example
    my $val;
sub canmod : lvalue {
# return $val; this doesn't work, don't say "return"
$val;
}
sub nomod {
$val;
}
Now see the magic
    canmod() = 5;   # assigns to $val in the above subroutine
nomod() = 5; # ERROR

Passing Lists to Subroutines

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 @
_. All the followings are valid
mysub(1,2,3);
@args = (2,3);
mysub(1,@args);
@args = (1,2,3);
mysub(@args);
Finally when we receive thes values in@_ variable then we can not recognize if we had passed one array or two value arraysbecause finally it is getting merged into one.

o

If you want to work with and identify the individual lists passed to Perl, then you need to use references:
(@listc, @listd) = simplesort(@lista, @listb);
The leading character tells Perl to supply a reference, or pointer, to the array. A reference is actually just a scalar, so we can identify each list by assigning the reference to each array within our subroutine. Now you can write your subroutineas follows:
sub simplesort
{
my ($listaref, $listbref ) = @_;

# De-reference the array list
my (@lista) = @$listaref;
my (@listb) = @$listbref;
# Now you can play with both arrays.
}

Passing Hashes to Subroutines

When you supply a hash to a subroutine or operator that accepts a list, the hash is automatically translated into a list of key/value pairs. For example:
%hash = ('name' => 'Tom', 'age' => 19);
print %hash;
This will output .nameTomage19.. However, the same process works in reverse, so we can extract a list and convert it to a hash:
sub display_hash
{
my (%hash) = @_;
foreach (%hash)
{
print "$_ => $hash{$_}n";
}
}
In this case, we output the key/value pairs of the hash properly, displaying each pair on its own line. As with arrays, care needs to be taken if you expect to pick out a single hash from a list of arguments. The following will work because we extract the hash last:
sub display_has_regexp
{
my ($regex, %hash) = @_;
...
}
while this one won.t because we try to extract the hash first (there will be an extra element, and Perl won.t know how to assign this to the hash):
sub display_has_regexp
{
my (%hash, $regex) = @_;
...
}
If you want to work with multiple hashes, then use references. For example, the following subroutine returns the key intersection of two hashes:
sub intersection
{
my ($hasha, $hashb) = @_;
my %newhash;
foreach my $key (keys %{$hasha})
{
$newhash{$key} = $$hasha{$key} if (exists $$hashb{$key});
}
return %newhash;
}
To use the subroutine:
%hasha = ('a' => 'b',
'b' => 'b',
'c' => 'b');
%hashb = ('b' => 'b',
'c' => 'b',
'd' => 'b');
%newhash = intersection(%hasha, %hashb);
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s