Invoking Subroutines

By Andrew Johnson, ITworld |  How-to Add a new comment

A subroutine can be invoked a couple of different ways, and I sometimes
get asked when different methods are needed and what are the
differences among them. The question arises because people see code
using the ampersand (&) for function calls, other code that does not,
some code using parentheses, and some that does not.

Do we need the ampersand? When? The short answer is no, we do not need
the ampersand to invoke a function (but we do need it to take a
reference to an existing named function). Here's the main ways of
calling a function you've created named 'foo':

&foo(); # calls foo with no arguments
&foo($arg); # calls foo with $arg
foo(); # calls foo with no arguments
foo($arg); # calls foo with $arg

Doesn't seem to be much difference right? Well, if 'foo' is defined
with prototypes, then the versions above using the ampersand disable
those prototypes. Using a module where the routines have prototypes and
simply ignoring those prototypes by using the ampersand to call its
functions, could lead to subtle bugs.

All of the above used parentheses in the calls, but parentheses are not
always required. If you define or declare the subroutine prior to
calling it, then you may call it without parentheses:

sub foo {
print "you passed: @_\n";
}
foo;
foo 1, 2, 3;

Now you can call 'foo' without parentheses just like a built-in routine
may be called without parentheses. However, if you use the ampersand
and no parentheses, something very different happens: The function is
called using the current value of @_ as the argument list. This can be
used to pass arguments on from one function to another:

foo(1,2,3); # call foo with (1,2,3)
foo(); # calls foo with no arguments

sub foo {
die "no arguments given to foo" unless @_;
&bar; # same as: bar(@_);
}

sub bar {
print "You passed: (@_ ) to foo()\n";
}

The above all holds true for subroutine references as well (except
there aren't prototypes on sub references):

my $sref = sub{print "You passed: @_\n";};
@_ = (1,2,3);

&$sref(); # calls sref with no args
$sref->(); # calls sref with no args
&$sref; # calls sref with @_

However, if you want to take a reference to a named subroutine, then
you have to use an ampersand to get the reference:

sub foo {print "You passed: @_\n"}

my $sref = \&foo;
$sref->(1,2,3);

With all this variation, what's the best way to do things? Different
folks have different answers, but my answer is to always call a
function without the ampersand, and always use parentheses. This rule
is very simple, leads to clean code, and won't give you surprises
regarding prototypes if you ever decide to use them (or use another
module that uses them).

Next Week: MD5 Checksums with Digest::MD5

    Add a comment

    Post a comment using one of these accounts
    Or join now
    At least 6 characters

    Note: Comment will appear soon after you have activated your account.
    Obscene/spam comments will be removed and accounts suspended.
    The information you submit is subject to our Privacy Policy and Terms of Service.

    ITworld LIVE

    Ask a question

    Ask a Question