Siaris
Simple Things
Syndicate: full/short
Siaris
Categories
General0
Misc0
News2
Programming2
LanguageBits0
Perl50
Ruby10
VersionControl1
Article Calendar
<= July, 2014
S M T W T F S
12345
6789101112
13141516171819
20212223242526
2728293031
Search this blog

Key links
External Blogs
Brought to you by ...
Ruby
1and1.com

Invoking Subroutines

Andrew L. Johnson (First published by ItWorld.com 2001-01-25)

There are a couple of different ways to invoke a subroutine, and I sometimes get asked which way is needed when and what are the differences among them. The question arises because people see some code that uses the ampersand (&) for function calls, and other code that does not, and some code that uses parentheses and some that does not.

Do we need the ampersand, and if so, 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, there is one difference and that is that if ‘foo’ is defined with prototypes, the versions above using the ampersand disable those prototypes (which could lead to subtle bugs if you are using a module where the routines have prototypes and you are simply ignoring those prototypes by using the ampersand to call its functions).

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 with regards to prototypes if you ever decide to use them (or use another module that uses them).

(note: &bar; and bar(@_) are actually slightly different: the former calls bar() reusing the current @_ array, the latter passes a copy of the @_ array — not that makes a difference for most purposes).