Broad Network


Passing and Returning Variables in Perl Function

Perl Function Explained – Part 2

Perl Course

Foreword: In this part of the series I explain how to pass and return scalar, array and hash variables to Perl functions; I also explain how to pass and return their references.

By: Chrysanthus Date Published: 8 Sep 2015

Introduction

This is part 2 of my series, Perl Function Explained. In this part of the series I explain how to pass and return scalar, array and hash variables to Perl functions; I also explain how to pass and return their references. You should have read the previous part of the series before reaching here, as this is the continuation.

Passing Variables
Scalars
The following code illustrates how to pass scalar variables to a function:

use strict;

    sub fn
        {
            print "$_ " foreach @_;
        }

    fn("one", "two");

The output is: one two. When arguments are sent to a function (definition), they arrive into the special local array, @_ of the function. In the statement in the above function definition, $_ represents each element in any array that is typed after foreach. Do not confuse between $_ and the array elements of the special @_ array, which are $_[0], $_[1], $_[2], etc. In the code, "$_ " is to be replaced by the value of $_ followed by a space, since a variable in double quotes expands.

The order of the scalar arguments are maintained in @_. Also note that in the above code, @_ does not need to be in parentheses in the foreach statement.

Passing Arrays
The following code illustrates how to pass an array to a function:

use strict;

    my @arr = ("black", "white", "bisque");

    sub fn
        {
            foreach my $i (0..4)
                {
                    print "$_[$i] ";
                }
        }

    fn("one", "two", @arr);

I tried the code and I had,

    one, two, black, white, bisque

When an array is passed, the order of the values of the array are maintained in the @_ array, which is local to the function. In the code, $i is a counter and (0..4) is the range of indices of the @_ array elements. $_[$i] is the identifier for each element in the special @_ array.

Well, since the above foreach loop has just one statement, it could have been shortened to:

    print "$_ " foreach @_;

where $_ is for any array typed after foreach, and not just @_ .

Remember that in Perl, the foreach reserved word means exactly the same thing as the reserved word, for.

You can pass an anonymous (no name) array to a function. The following code illustrates this:

use strict;

    sub fn
        {
            foreach my $i (0..4)
                {
                    print shift, " ";
                }
        }

    fn("one", "two", ("black", "white", "bisque"));

With an anonymous array, the order sent is still maintained in @_.

There are four default functions for the special local @_ function array. The functions (operators) are: push, pop, shift, and unshift. These functions can be used with different arrays, but they are the default functions to @_ , because when using in relation to @_, they do not need any argument.

The above foreach loop actually has two statements in one statement. The above foreach loop cannot be replaced by the following statement, for the reason I give below:

            print shift, " " foreach @_;    #wrong

Now, you use a simple (foreach) statement instead of a compound statement (with a block), when the action (block) would have only one statement. If the action would have more than one statement, then use the compound statement.

In this statement that will not work (properly), there are actually two statements in one statement, in the action, that precedes the foreach modifier: print() with whatever argument it has, is a statement on its own; shift() with whatever argument it has, is also a statement on its own. So this apparent simple foreach statement actually has two statements (expressions) and so it cannot work. For a simple statement to work, it should have only one statement (expression) in front of the modifier. Note that the previous simple statements that have worked, have only one statement (expression) in front of the modifier.

Passing a Hash
A hash is a list like an array, but it is made up of key/value pairs. You pass a hash in the same way that you pass an array. However, when you pass a hash directly (non-reference) the order of the pairs in @_ is not necessarily maintained. However, the relationship between a key and its corresponding value is maintained. The following code illustrates how to pass a hash directly to a function:

use strict;

    my @arr = ("black", "white", "bisque");

    my %ha = (
                 Apple => "purple",
                 Banana => "yellow",
                 Pear => "green",
                 Lemon => "green"
             );


    sub fn
        {
            print "$_ " foreach @_;
        }

    fn("one", "two", @arr, %ha);

I tried the code and I had,

    one two black white bisque Pear green Apple purple Lemon green Banana yellow

You can pass an anonymous hash. Still with an anonymous hash, the order of the pairs may not be maintained. Try the following code:

use strict;

    sub fn
        {
             foreach my $i (0..12)
                {
                    my $var = shift;
                    print $var, " ";
                }
        }

    fn("one", "two", ("black", "white", "bisque"), (Apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green"));

I tried the code and I had,

    one two black white bisque Apple purple Banana yellow Pear green Lemon green

The shift function has been used to remove the top element of @_ one-by-one and sent to $var, for each iteration. You can still type the shift function as:

    shift()

or

    shift(@_);

Note again: when you pass an array or hash directly, the array or hash flattens out in @_, and the order of the hash pairs may not be maintained.

Pass by Reference
When you pass a variable directly to a function, you end up with two copies of the variable in memory. When you pass a variable by reference, you end up with one copy (instance) of the variable in memory.

When you define a scalar variable (declared and assign) and then you pass the variable to a function, the scalar variable defined has one copy of the value and the @_ array local to the function, has another copy of the value.

When you define an array variable, and then you pass the variable to a function, the array variable defined has one copy of all its values and the @_ array has a second copy of the same values.

When you define a hash variable, and then you pass the variable to a function, the hash variable defined has one copy of all its key/value pairs and the @_ array has a second copy of the same key/value pairs.

So to safe memory, you can pass a variable by reference. Note: when passed by reference, any change made to the reference in the function actually occurs in the variable declared outside the function. When passed by reference, there is only one copy of the variable (value).

Passing a Scalar Reference
The following code shows how a scalar variable can be passed by reference:

use strict;

    my $var = 55;

    sub fn
        {
            print ${$_[0]};
        }

    fn(\$var);

The reference to the variable is \$var. Note how $_[0] that has the reference has been dereferenced with ${ } to obtain the value. The same code could have been written as follows:

use strict;

    my $var = 55;
    my $ref = \$var;

    sub fn
        {
            print ${$_[0]};
        }

    fn($ref);

Here, instead of using the reference as argument in the function call, a variable holding the reference has been used.

Note: you dereference a scalar with ${}, an array with @{}, a hash with %{} and a function with &{}.

Passing an Array Reference
The following code illustrates how to pass an array by reference:

use strict;

    my @arr = ("black", "white", "bisque");

    sub fn
        {
            print "$_[0] $_[1] ";
            print "$_ " foreach @{$_[2]};
        }

    fn("one", "two", \@arr);

The output is:

    one two black white bisque

In the function call, the first argument is "one" and the second argument is "two". The third argument is a reference to the array. In the function definition, the first value in @_ is "one" and the second value in @_ is "two". The third value in @_ is a reference to the passed array. Note how this reference has been dereferenced with @{ } in order to obtain the values.

Passing a Hash Reference
The following code illustrates how to pass a hash by reference:

use strict;

    my @arr = ("black", "white", "bisque");

    my %ha = (
                 Apple => "purple",
                 Banana => "yellow",
                 Pear => "green",
                 Lemon => "green"
             );

    sub fn
        {
            print "$_[0] $_[1] ";
            print "$_ " foreach @{$_[2]};
            print "$_ " foreach %{$_[3]};
        }

    fn("one", "two", \@arr, \%ha);

I tried the code and I had,

    one two black white bisque Lemon green Pear green Banana yellow Apple purple

The first argument of the function call is "one" and the second is, "two". The third argument is a reference to an array passed. The fourth is a reference to the hash passed. The third value in the @_ array is a reference to the array passed. The fourth value in the @_ array is a reference to the hash passed. Note how the hash has been dereferenced with %{ }.

Returning Variables
No matter what was passed to a function, it can return a scalar, a list (array) or a hash.

Returning a Scalar
The following code illustrates how a scalar can be returned:

use strict;

    sub fn
        {
            #statements
            return "seen";
        }

    my $ret = fn();

    print $ret;

The return value is a literal. The return value can be in a variable as in the function:

    sub fn
        {
            #statements
            my $var = "seen";
            return $var;
        }

A scalar returned has to be received by a scalar in the calling function statement. If the return statement is,

    return;

then the calling function statement has to be something like,

   fn()

In this case the return value is void and is not received by the calling function statement. This is void context.

Returning a List
A list is in the form of an array or a hash. If you return an array, then the calling function statement should have an array to receive it, as in

    my  @arra = fn();

If you return a hash, then the calling function statement should have a hash to receive it, as in

    my  %has = fn();

If you receive a list with a scalar, then it is the last value of the list that will be taken. In the case of a hash, it is the last value (not key) that will be received.

Returning a Reference
You can return the reference of a scalar or array or hash. The returned reference is received by a scalar variable. In this case, you do not have two copies of returned data. You can go on to use the scalar, while dereferencing it appropriately (scalar or array or hash).

There are eight variable types in Perl, which are: scalar, array, hash, function, label, filehandle, typeglob and format. You usually pass and return scalar, array and hash. Occasionally, you pass a function, but you do not return a function - see later.

That is it for this part of the series. We stop here and continue in the next part.

Chrys

Related Links

Perl Basics
Perl Data Types
Perl Syntax
Perl References Optimized
Handling Files and Directories in Perl
Perl Function
Perl Package
Perl Object Oriented Programming
Perl Regular Expressions
Perl Operators
Perl Core Number Basics and Testing
Commonly Used Perl Predefined Functions
Line Oriented Operator and Here-doc
Handling Strings in Perl
Using Perl Arrays
Using Perl Hashes
Perl Multi-Dimensional Array
Date and Time in Perl
Perl Scoping
Namespace in Perl
Perl Eval Function
Writing a Perl Command Line Tool
Perl Insecurities and Prevention
Sending Email with Perl
Advanced Course
Miscellaneous Features in Perl
Perl Two-Dimensional Structures
Advanced Perl Regular Expressions
Designing and Using a Perl Module
More Related Links
Perl Mailsend
PurePerl MySQL API
Perl Course - Professional and Advanced
Major in Website Design
Web Development Course
Producing a Pure Perl Library
MySQL Course

BACK NEXT

Comments

Become the Writer's Fan
Send the Writer a Message