Search code examples
perlgetopt-long

In newer Getopt::Long How do I set default optional values


In Perl's Getopt::Long version 2.39 I could use

use Getopt::Long qw( :config gnu_getopt );
GetOptions(
   \my %opts, 
   "codon-view|c:20",    # Optional value, default 20
   "consensus|C:50", 
   ...
)

to indicate that if I use -c the default value would be 20 put in %optsunder key codon-view when -c is given but no explicit value for it is there. On the other hand -c or --codon-view is not supplied, then no value in the hash table is stored for in %opts.

In 2.48 this no longer works and I don't see in Getopt::Long's documentation

$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.39
20

$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.48
[undef]

How can I achieve the old behavior?

Help!


Solution

  • This is a change introduced in 2.48.

    $ perl -E'
       use Getopt::Long qw( :config gnu_getopt );
       say $Getopt::Long::VERSION;
       GetOptions(\my %opts, "codon-view|c:20");
       say $opts{"codon-view"} // "[undef]"
    ' -- -c
    2.47
    20
    
    $ perl -E'
       use Getopt::Long qw( :config gnu_getopt );
       say $Getopt::Long::VERSION;
       GetOptions(\my %opts, "codon-view|c:20");
       say $opts{"codon-view"} // "[undef]"
    ' -- -c
    2.48
    [undef]
    

    I'm not sure, but I think it was done unintentionally, so I filed a bug report.


    use Getopt::Long qw( :config gnu_getopt );
    

    is short for

    use Getopt::Long qw( :config gnu_compat bundling permute no_getopt_compat );
    

    How invested are you in using gnu_compat?

    $ perl -E'
       use Getopt::Long qw( :config gnu_getopt );
       say $Getopt::Long::VERSION;
       GetOptions(\my %opts, "codon-view|c:20");
       say $opts{"codon-view"} // "[undef]"
    ' -- -c
    2.48
    [undef]
    
    $ perl -E'
       use Getopt::Long qw( :config gnu_compat bundling permute no_getopt_compat );
       say $Getopt::Long::VERSION;
       GetOptions(\my %opts, "codon-view|c:20");
       say $opts{"codon-view"} // "[undef]"
    ' -- -c
    2.48
    [undef]
    
    $ perl -E'
       use Getopt::Long qw( :config bundling permute no_getopt_compat );
       say $Getopt::Long::VERSION;
       GetOptions(\my %opts, "codon-view|c:20");
       say $opts{"codon-view"} // "[undef]"
    ' -- -c
    2.48
    20
    

    gnu_compat controls whether --opt= is allowed, and what it should do. Without gnu_compat, --opt= gives an error. With gnu_compat, --opt= will give option opt and empty value. This is the way GNU getopt_long() does it.

    So if you're ok with --codon-view= assigning zero to $opts{"codon-view"}, simply use

    use Getopt::Long qw( :config bundling permute no_getopt_compat );
    

    instead of

    use Getopt::Long qw( :config gnu_getopt );