Search code examples
perlfunctionsubroutine

How to pass optional arguments to a function


I'm trying to make a function for a module accept optional arguments in the form of:

function(arg1, optional1 => opt1, optional2 => opt2, ..);

Yet I can't find anywhere that shows a good explanation how to do this. I came up with the following solution to accept email, alpha and html arguments, but it's extremely convoluted and I can't believe there isn't a shorter way to accomplish this:

sub test
{
    my ($s, @args) = @_;
    my $alpha = 1;
    my $html = 0;
    my $email = 0;
    for(my $i = 0; $i < scalar(@args); $i++)
    {
        if($args[$i] eq "alpha")
        {
            $i++;
            $alpha = $args[$i];
        }
        elsif($args[$i] eq "email")
        {
            $i++;
            $email = $args[$i];
        }
        elsif($args[$i] eq "html")
        {
            $i++;
            $html = $args[$i];
        }
    }
    return ($alpha, $email, $html);
}

my ($a, $b, $c) = test("stuff", ndhgffs => 1, email => 1, alpha => 0);

print $a . $b . $c;

EDIT:

Thanks to the answer below and comments below that, this solved it:

sub test
{
   my ($s, %opts) = @_;
   my $email = $opts{'email'} // 0;
   my $alpha = $opts{'alpha'} // 1;
   my $html = $opts{'html'} // 0;
   return ($alpha, $email, $html);
}

Solution

  • sub function {
       my $arg1 = shift;
       my $arg2 = shift;
       my %opts = @_;
       my $optional1 = delete($opts{$optional1});
       my $optional2 = delete($opts{$optional2});
       croak("Unrecognized parameters ".join(' ', keys(%opts))) if %opts;
       ...
    }
    

    or

    sub function {
       my ($arg1, $arg2, %opts) = @_;
       my $optional1 = delete($opts{$optional1});
       my $optional2 = delete($opts{$optional2});
       croak("Unrecognized parameters ".join(' ', keys(%opts))) if %opts;
       ...
    }
    

    Notes:

    • If you don't want to bother checking for unrecognized options, you don't need delete.

    • You can easily assign default values when an argument is omitted or undef using

      my $arg = delete($opts{$arg}) // 'default';   # Perl 5.10+