Named Parameters for Subroutine Calls
26 Jul 01 -

Perl doesn’t have typed or named parameters for subroutines, all parameters are passed in the @_ array as a flat list. However, since a list can also be a hash, we can fake it and create subroutines that can be called like:

    my $status = login( -username => $user,
                        -password => $pass,
                        -host     => $host,

This assumes we have already obtained values for $user and $pass from the user input or the command line (or wherever) and we have a function named login() that is apparently going to log us in to whatever $host is. Without worrying about the specifics of the function itself, let’s look at how it can process the arguments:

    sub login {
        my %args = @_;
        # do stuff

Easy right, so what benefit do we get? Well, we get two benefits, the first of which is that our calling code is rather self-documenting (even if we chose horrible names for the variables themselves, the hash keys give it all away). Another important benefit is that we no longer have to worry about which order we give the arguments, and neither does our subroutine! We can call it like above, or like either of these:

    my $status = login( -password => $pass,
                        -host     => $host,
                        -username => $user,

    my $status = login( -password => $pass,
                        -username => $user,
                        -host     => $host,

And, as a bonus, if want a subroutine where some or all of the arguments are optional (in any order), we can do that too:

    sub draw_rect3D {
        my %args = shift;
        $args{-length} ||= 1;
        $args{-width}  ||= 1;
        $args{-height} ||= 1;
        $args{-units} = $args{-units} eq 'in'? 'in' : 'cm';
        # get to work

Now we can call this and supply any of the parameters, all of the parameters, or none of the parameters (the default will be a 1 centimeter cube):

    draw_rect3D(-length => 2, -units => 'in'); # 2 x 1 x 1 inches
    draw_rect3D(-length => 5, -wdith => 2);    # 5 x 2 x 1 centimeters
    draw_rect3D(-length => 5,
                -height => 10,
                -units  => 'in',
                -width  => 3,
               );                  # 5 x 3 x 10 inches

This is quite unlike our regular way of just using the argument array as an array — in that case the order you use must always be the same, and optional arguments must be at the end.

You will see this style of function used often for Object constructor methods (and other OO methods) and it is widely used in the various Tk routines and methods (for GUI programming). But you can use this technique with any regular subroutine — all we are doing is using the argument list as a hash instead of a list or array.