Aristides Aristides - 2 years ago 134
PHP Question

Perl subroutine arguments

I have been reading about Perl recently and am slightly perplexed about how Perl handles arguments passed to subroutines.

In a language like Python, Java or PHP, a function definition takes the form (in pseudocode):

function myFunc(arg1, arg2) {
// Do something with arg1 and arg2 here

Yet in Perl it's just:

sub mySub {
# @_ holds all arguments passed

And as I understand it, that's the only way to do it.

  • What if I want to restrict the caller to only pass 2 arguments?

  • Isn't this just Perl not allowing anything but variable-number arguments in other languages (i.e. Python, C, etc)?

  • Wouldn't that become a problem at some point?

  • What about all the default argument-number checking in other languages? Would one have to do that explicitly in Perl? For instance

    sub a_sub {
    if (@_ == 2) {
    # Continue function
    else {
    return false

Answer Source

You are wary of the Perl environment because it is quite different from the languages you have come across before.

The people who believe in strong typing and function prototypes will disagree here, but I believe that restrictions like that are rarely useful. Has C really caught you passing the wrong number of parameters to a function often enough to be useful?

It is most common in modern Perl to copy the contents of @_ to a list of lexical scalar variables, so you will often see subroutines starting with

sub mysub {
  my ($p1, $p2) = @_;
  ... etc.

that way, all parameters that are passed will be available as elements of @_ ($_[0], $_[1] etc.) while the expected ones are named and appear in $p1 and $p2 (although I hope you understand that those names should be chosen appropriately).

In the particular case that the subroutine is a method, the first parameter is special. In other languages it is self or this, but in Perl it is simply the first parameter in @_ and you may call it what you like. In those circumstances you would see

sub method {
  my $self = shift;
  my ($p1, $p2) = @_;
  ... etc.

so that the context object (or the name of the class if it is a class method) is extracted into $self (a name assumed by convention) and the rest of the parameters remain in @_ to be accessed either directly or, more usually, copied to local scalar variables as $p1, $p2 etc.

Most often the complaint is that there is no type checking either, so I can pass any scalar I like as a subroutine parameter. As long as use strict and use warnings are in context, even this is generally simple to debug, simply because the operations that the subroutine can perform on one form of scalar are usually illegal on another.

Although it was originally more to do with encapsulation with respect to object-oriented Perl, this quote from Larry Wall is very relevant

Perl doesn't have an infatuation with enforced privacy. It would prefer that you stayed out of its living room because you weren't invited, not because it has a shotgun

C was designed and implemented in the days when it was a major efficiency boost if you could get a faulty program to fail during compilation rather than at run time. That has changed now, although a similar situation has arisen with client-side JavaScript where it actually would be useful to know that the code is wrong before fetching the data from the internet that it has to deal with. Sadly, JavaScript parameter checking is now looser than it should be.


For those who doubt the usefulness of Perl for teaching purposes, I suggest that it is precisely because Perl's mechanisms are so simple and direct that they are ideal for such purposes.

  • When you call a Perl subroutine all of the parameters in the call are aliased in @_. You can use them directly to affect the actual parameters, or copy them to prevent external action

  • If you call a Perl subroutine as a method then the calling object or class is provided as the first parameter. Again, the subroutine (method) can do what it likes with @_

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download