Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi all.

I just noticed something I can't understand with Getopt::Long yesterday. From the manual:

Options with multiple values
Options sometimes take several values. For example, a program could use multiple directories to search for library files:
    --library lib/stdlib --library lib/extlib
To accomplish this behaviour, simply specify an array reference as the destination for the option:
    GetOptions ("library=s" => \@libfiles);
Alternatively, you can specify that the option can have multiple values by adding a "@", and pass a scalar reference as the destination:
    GetOptions ("library=s@" => \$libfiles);

And this is what I have

use strict; use warnings; use Getopt::Long; use Data::Dumper; ##### THREE VARIATIONS ##### ## Does work: my $options_ok = GetOptions ('option=s@' => \(our $option_array_ref)); my @option_array = @$option_array_ref; ## Does work: our $option_array; my $options_ok = GetOptions ('option=s' => \@option_array); ## Doesn't work: my $options_ok = GetOptions ('option=s' => \(our @option_array)); ##### COMMON CODE ##### if (not $options_ok) { print "Problem with options\n"; exit -1; } print Dumper(@option_array); exit 0;

Run with something like:

perl script.pl --option OPTION1 --option OPTION2
The strange thing is that this works for a single argument option:
my $options_ok = GetOptions ('option=s' => \(our $option_variable));

So I had a bunch of those (saves lines for declaration of the variables), and when I wanted to switch one into a multi-value version, it didn't behave as I expected…

Wonder if anybody has an explanation, it must have to do with how references to variables and strings are returned on declaration, but it's not clear in my mind.
Any insights appreciated.

Cheers, Mark Collins.

Replies are listed 'Best First'.
Re: Issue with multiple options for a Getopt::Long argument
by NetWallah (Canon) on Jan 22, 2018 at 21:12 UTC
    \(our @option_array)
    That is a reference to a COPY of @option_array.

    The COPY receives the values, not the original @option_array.

    (Update : See ikegami's correction below.)

    Just use :

    \@option_array
    Here is a test case .. for some reason,the copy will not print unless it is assigned to something.
    >perl -E "my @x; say qq|Orig=|,\@x; say qq|Copy:|,$_=\(@x)" Orig=ARRAY(0xdb84d8) Copy:SCALAR(0xed8c78)

                    Is a computer language with goto's totally Wirth-less?

      That is a reference to a COPY of @option_array.

      No, nothing is being copied.

      In list context, \(@array) is equivalent to \($array[0], $array[1], ..., $array[-1]), which is equivalent to \$array[0], \$array[1], ..., \$array[-1].

      In scalar context, \(@array) is equivalent to \($array[0], $array[1], ..., $array[-1]), which is equivalent to \$array[-1].

      The above also applies to \(our @option_array). The OP wants \our @option_array (no parens), which returns a reference to the array.

        YES! It had to be something to do with the way I was getting the reference from the declaration. Never thought to remove the parentheses! Thanks a bunch ikegami!

        Regards, Mark.