essential essential - 1 year ago 70
Perl Question

How to pass optional parameters to a Perl subroutine?

I wanted to pass two arguments to my subroutine. The first parameter is required, the second parameter I want to be optional. Actually it works for non-array parameter in this script:

deftest ("string value test",9);

sub deftest{
my ($strvalue, $num) = @_;
if (defined $num){
print "\nCHECK 1 - Defined value $num";
} else {
$num //= 99;
print "\nstrvalue: $strvalue num: $num\n";

When I invoke this subroutine with ("string value test",9); then on the screen:

CHECK 1 - Defined value 9
strvalue: string value test num: 9

When I don't enter the second argument, then the value is 99. So this works fine.

The problem is, when I use the array in the first argument:

my @arrSwap = (1,2,3);
deftest2 (@arrSwap,5);

sub deftest2{
my (@arrSwap, $num) = @_;
if (defined $num){
print "\n\nCHECK 2 - Defined val $num";
} else {
$num //= 55;
print "\narrSwap $arrSwap[1] num: $num\n";

After invoking this subroutine with deftest2 (@arrSwap,5); then on the screen I have only:
arrSwap 2 num: 55

(but 5 would be expected as it is defined).

Why it doesn't work with the array?

Answer Source

Because perl passes a single list as arguments, and assigning my ( @arrSwap, $num ) = @_ will always mean an empty $num, because @arrSwap will consume the entirety of the input.

If you want to do this, you need to pass a reference

    my @arrSwap = ( 1,2,3 ); 
    deftest2 ( \@arrSwap, 5);  

    sub deftest2 { 
        my ( $arrSwap_ref, $num ) = @_; 
        $num //= 55;
        print "\narrSwap", $arrSwap -> [1], " num: $num\n";

Otherwise perl simply has no way to tell whether the last number is part of the list you sent, or an optional parameter.