I’m using Getopt::Lucid to process CLO and I’ve run into an interesting and unexpected problem. The following code:
push @clo_spec, map { Switch($_) } qw(-c -m -s -p),
map { Switch($_) } qw(--help --man --usage --version),
map { Switch($_) } qw(--debug --verbose),
map { Param($_) } keys %$rc_spec_ref
;
my $clo_o = Getopt::Lucid->getopt(\@clo_spec);
generates the following error:
'Getopt::Lucid::Spec=HASH(0x9383847)' is not a valid option name/alias
Now, Getopt::Lucid is configured by quoting an string expression representing valid options and then passing those strings to one of six subroutines which return blessed hashes. Each subroutine represents a type of option; switch, counter, parameter, list or key-pair.
The interesting part is that if any three map expressions are removed,
push @clo_spec, #map { Switch($_) } qw(-c -m -s -p),
map { Switch($_) } qw(--help --man --usage --version),
#map { Switch($_) } qw(--debug --verbose),
#map { Param($_) } keys %$rc_spec_ref
;
then everything works fine. The even more interesting part is that if you encase each map expression in parentheses, everything also works fine:
push @clo_spec, (map { Switch($_) } qw(-c -m -s -p)),
(map { Switch($_) } qw(--help --man --usage --version)),
(map { Switch($_) } qw(--debug --verbose)),
(map { Param($_) } keys %$rc_spec_ref)
;
The above leads me to believe that this problem isn’t related to a bug in Getopt::Lucid. Also, I considered the above fix after looking at the map function’s reference which mentions that sometimes map can get confused with commas. Perl will flatten embedded lists, and the surrounding parentheses seem to have the effect of delineating each map expression, but I really don’t understand what’s going on.
Can someone please explain?
The
mapfunction takes a list as an argument and generates a list as a result. You can chainmapstatements together (feeding the output of onemapas the input to another) which is what your first example does. Adding parentheses around the individualmapoperators breaks the chain.When reading chained
map(orgrep) statements, read from right to left.The last
mapcallsParam()for each key from%$rc_spec_refand returns the results. Themapabove that callsSwitch()for the values--debug,--verbose, and each result from the lastmap. Themapblocks above those get even longer argument lists with the flags inqw()having the results of the othermapblocks concatenated with them.Adding parentheses around each
mapblock changes the way the code parses, causing eachmapto be treated individually rather than being daisy-chained.